assert / assert_not in ruby - ruby-on-rails

when do we use assert and asert_not in ruby on rails tests, what's the difference between the to?
Example:
test 'email should not be too long' do
#user.email = 'a' * 244 + '#example.com'
assert_not #user.valid?
end
test 'email validation should accept valid addresses' do
valid_addresses = %w[user#example.com USER#foo.COM A_US-ER#foo.bar.org
first.last#foo.jp alice+bob#baz.cn]
valid_addresses.each do |valid_address|
#user.email = valid_address
assert #user.valid?, "#{valid_address.inspect} should be valid"
end
end

Use assert_not when you expect the result to be false.
https://apidock.com/rails/ActiveSupport/Testing/Assertions/assert_not
Use assert when you expect the result to be true.
https://docs.ruby-lang.org/en/2.1.0/Test/Unit/Assertions.html

Related

email validation arguments - Wrong number of args in test Michael Hartl Rails tutorial

Followed the instructions in chapter 6, tutorial test should be GREEN(no failures/errors), but I'm receiving the below error
Expecting the test results to pass. From the error, I understand there's a missing an arg, but unsure what to change
user_test.rb
test "email validation should accept valid addresses" do
valid_addresses = %w[user#example.com USER#foo.COM A_US-ER#foo.bar.org
first.last#foo.jp alice+bob#baz.cn]
valid_addresses.each do |valid_address|
#user.email = valid_address
assert #user.valid?, "#{valid_address.inspect} should be valid"
end
end
test "email validation should reject invalid addresses" do
invalid_addresses = %w[user#example,com user_at_foo.org user.name#example. foo#bar_baz.com foo#bar+baz.com]
invalid_addresses.each do |invalid_address|
#user.email = invalid_address
assert_not #user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
#user.rb
class User < ApplicationRecord
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
end
ERROR["test_email_validation_should_accept_valid_addresses", UserTest, 0.41518251600001577]
test_email_validation_should_accept_valid_addresses#UserTest (0.42s)
ArgumentError: ArgumentError: wrong number of arguments (given 1, expected 2)
test/models/user_test.rb:41:in test'
test/models/user_test.rb:41:inblock in '
I have now managed to get this working. Appears the indentation on the tests was causing AWS cloud9 to throw an error asking for an expected keyword_end. I believe adding an extra end was creating the above error message. Solution: indented code correctly using the keyword_end in the correct places fixed my problem.

What is the RSpec syntax equivalent for assert (minitest)

I am following Michael Hartl's Ruby on Rails tutorial. I observe that he used minitest to run his tests. I use RSpec. Below is a line of code from the tutorial I want to replicate with RSpec
test "email validation should accept valid addresses" do
valid_addresses = %w[user#example.com USER#foo.COM A_US-ER#foo.bar.org
first.last#foo.jp alice+bob#baz.cn]
valid_addresses.each do |valid_address|
#user.email = valid_address
assert #user.valid?, "#{valid_address.inspect} should be valid"
end
end
This is how I will do this in with RSpec.
it "email validation should accept valid addresses" do
valid_addresses = ["user#example.com", "USER#foo.COM", "A_US-ER#foo.bar.org",
"first.last#foo.jp", "alice+bob#baz.cn"]
valid_addresses.each do |valid_address|
user.email = valid_address
expect(#user.valid?).to be true, "#{valid_address.inspect} is not correct"
end
end
However, I get Argument error when I run this test. It appears RSpec expects only one argument in test cases.
RSpec thinks that you're passing a single argument to the to method and two arguments to the be method, and hence it's giving you an error. It's seeing your statement as:
expect(#user.valid?).to(be(true, "#{valid_address.inspect} is not correct"))
So, you can change your spec to be the following, and it should work:
expect(#user.valid?).to be(true), "#{valid_address.inspect} is not correct"
Here, RSpec is seeing two arguments being passed to the to method, which is valid.
What exactly is the error message you are getting. It looks like you have a typo. Should
user.email = valid_address
be
#user.email = valid address
You're providing 2 arguments and the expect statement takes one.
expect(#user.valid?).to be true

Ruby on Rails User Test Fails

Doing the Ruby on Rails Tutorial and I'm getting strange error message when running the test.
My user_test.rb:
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
#user = User.new(name: "Example User", email: "user#example.com", password: "wordpass", password_confirmation: "wordpass")
end
test "should be valid" do
assert #user.valid?
end
test "name should be present" do
#user.name=" "
assert_not #user.valid?
end
test "email should be present" do
#user.email= " "
assert_not #user.valid?
end
test "name should not be too long" do
#user.name= "a" * 51
assert_not #user.valid?
end
test "email should not be too long" do
#user.email= "a" * 256
assert_not #user.valid?
end
test "email validation should accept valid addresses" do
valid_addresses = %w[user#example.com USER#foo.COM A_US-ER#foo.bar.org
first.last#foo.jp alice+bob#baz.cn]
valid_addresses.each do |valid_address|
#user.email = valid_address
assert #user.valid? , "#{valid_address.inspect} should be valid"
end
end
test "email validation should reject invalid addresses" do
invalid_addresses = %w[user#example,com user_at_foo.org user.name#example.
foo#bar_baz.com foo#bar+baz.com]
invalid_addresses.each do |invalid_address|
#user.email = invalid_address
assert_not #user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
test "email addresses should be unique" do
duplicate_user = #user.dup
duplicate_user.email = #user.email.upcase
#user.save
assert_not duplicate_user.valid?
end
test "password should be a minimum length" do
#user.password = #user.password_confirmation = "a" * 5
assert_not #user.valid?
end
end
The user.rb :
class User < ActiveRecord::Base
attr_accessor :name, :email , :password, :password_confirmation
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
end
One of the errors seems to be from the user definition, but I cannot find the source of error. Is it something due related to "validates" in user.rb file ? Any help will be much appreciated !!
FAIL["test_email_validation_should_accept_valid_addresses", UserTest, 0.061796445]
test_email_validation_should_accept_valid_addresses#UserTest (0.06s)
"user#example.com" should be valid
test/models/user_test.rb:34:in `block (2 levels) in <class:UserTest>'
test/models/user_test.rb:32:in `each'
test/models/user_test.rb:32:in `block in <class:UserTest>'
FAIL["test_should_be_valid", UserTest, 0.080466737]
test_should_be_valid#UserTest (0.08s)
Failed assertion, no message given.
test/models/user_test.rb:8:in `block in <class:UserTest>'
Thanks in advance for your help !
You are right, one of the errors is due to #user being invalid in the first test. Do the following in rails console, this should print out errors on user model:
#user = User.new(name: "Example User", email: "user#example.com", password: "wordpass", password_confirmation: "wordpass")
#user.valid?
pp #user.errors
Try different regex in user.rb
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
well everything looks fine. just run the command
rake db:test:prepare
and if this doesnt work either then
$rake db:delete
rake db:create
rake db:migrate
first one worked for me

Rails code validation working but Rspec tests failing

Can anyone see what's wrong about the Rspec? All of my tests for invalid emails are failing (i.e., they are supposed to not be valid but somehow are in Rspec), but in the actual code, it works fine, no emails that are bad are allowed. The validation even works in my console....
Two notes:
I realize the formatting isn't ideal... will work on that later. This was just me writing things individually without going through and DRYing it up yet.
I also realize there exists an easier way to validate these things individually in the model, but I wanted very custom messages without any reference to the attribute, and I disliked the roundabout way that I've read that needs to be done.
Model code
validate :create_validation, on: :create
def create_validation
errors[:base] << "Please enter a valid email address to continue" if self.email.blank? || (( /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i =~ self.email) == nil)
end
#The RegEx is from Michael Hartl's tutorial
Spec code
describe Signup do
before do
#signup = FactoryGirl.create(:signup)
end
subject { #signup }
describe "email tests" do
describe "invalid tests" do
# blank email
before { #signup.email = " " }
it { should_not be_valid }
# invalid format email
addresses = %w[user#foo..com, user#foo,com user_at_foo.org example.user#foo. foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
before { #signup.email = invalid_address }
it { should_not be_valid }
end
end
end
end
Factory girl code in spec helper
FactoryGirl.define do
factory :signup do |f|
f.email { Faker::Internet.email }
#... other attributes
end
end
As I understood code you validate only on create! But in tests you created object in before block and it is persisted in your tests - so validation is skipped.
Try this variant
describe Signup do
before do
#signup = FactoryGirl.build(:signup)
end
subject { #signup }
describe "email tests" do
describe "invalid tests" do
# blank email
before { #signup.email = " " }
it { should_not be_valid }
# invalid format email
addresses = %w[user#foo..com, user#foo,com user_at_foo.org example.user#foo. foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
before { #signup.email = invalid_address }
it { should_not be_valid }
end
end
end
end
I hope validation will be triggered for built but not saved record.
PS Or you can remove option on: :create

RSpec failling in email should not be valid

I'm new to all this rails/rspec and so on, so im trying to follow some tests that I had found in the project that i'm working and make sense, they were generated by scaffold but the app is very different and no tests were updated so im re-doing every test.
The problem is when I try to validate that invalid emails should make the user invalid it fails.
I know that it's ok because I already done tests and they pass without no problem.
It is possible that I'm looking at this the wrong way but ...
User_spec
describe "when email format is invalid" do
it "should be invalid" do
addresses = %w[user#foo,com user_at_foo.org example.user#foo.
foo#bar_baz.com foo#bar+baz.com]
addresses.each do |invalid_address|
#user.email = invalid_address
#user.should_not be_valid
end
end
end
User_test
test "fail save new user with an corrupt email" do
user = User.new
user.name = 'Someone Name'
user.password = '12345678'
user.email = 'Someone Name#gmail..com'
assert !user.save , "User was saved with an corrupt email"
end
The validation is done by devise and the failure message is "expected valid? to return false, got true"
---- edit ---
My user setup
...
describe User do
before :each do
#user = User.new(name: "Name of Names", email:"someone1#somewhere.com",password: "foobarfoobar", password_confirmation: "foobarfoobar" )
end
...
You could do something along the lines of this:
context "validations" do
describe "email" do
subject { FactoryGirl.create(:user, email: email) }
context "with an valid address" do
let(:email) { "valid#email.com" }
it { should be_valid }
end
context "with an invalid email address" do
let(:email) { "invalid.email.com" }
it { should_not be_valid }
end
end
end
So I'm assuming you are using FactoryGirl to create an valid user object. Just create new tests per invalid email, this way you can see which tests are passing and which aren't. Then you could TDD your way to green.

Resources