Open jcsherin opened 3 years ago
For Model, I have written some test :
class UserTest < ActiveSupport::TestCase
test "valid user" do
user = User.new(name: "Deep", email: "deep@gmail.com")
assert_not user.valid?
end
test "invalid without name" do
user = User.new(email: "deep@gmail.com", password: "test", role: "customer")
assert_not user.valid?, "user is valid without a name"
assert_not_nil user.errors[:name], "no validation error for name present"
end
test "invalid without email" do
user = User.new(name: "Deep", role: "owner", password: "test")
assert_not user.valid?
assert_not_nil user.errors[:email], "no validation error for email present"
end
test "invalid without role" do
user = User.new(name: "Deep", email: "deep@gmail.com", password: "test")
assert_not user.valid?
assert_not_nil user.errors[:role], "no validation error for role present"
end
test "invalid without pasword" do
user = User.new(name: "Deep", email: "deep@gmail.com", role: "owner")
assert_not user.valid?
assert_not_nil user.errors[:pasword], "no validation error for pasword present"
end
end
and when i run it:
bin/rails test test/models/user_test.rb
Running via Spring preloader in process 9185
Run options: --seed 18223
# Running:
.....
Finished in 0.204587s, 24.4395 runs/s, 43.9911 assertions/s.
5 runs, 9 assertions, 0 failures, 0 errors, 0 skips
Are tests supposed to be like this?
You are definitely on the right track.
When you test user.valid?
you are testing the ActiveRecord::Validations
API. This is unnecessary because you can move forward with the assumption that it would be tested in that project. This can be generalized. You do not need to test any third-party library/framework API within your application.
You should write test for your own code like: https://github.com/Deep-Codes/cafeman/blob/7c4f91b4ba42bf6ca229aa21e0be9f2ddfb427a3/app/models/user.rb#L7-L9
Hey sorry I was out yesterday
I tried some stuff
This Registers a new User:
require "test_helper"
class RegisterUsers < ActionDispatch::IntegrationTest
test "can register" do
assert_difference("User.count") do
post "/users/",
params: { email: "test@email.com ", password: "test_password", role: "customer", name: "test_name" }
end
assert_response :redirect
follow_redirect!
assert_equal "/", path
end
end
Results:
❯ bin/rails test test/integration/register_user_test.rb
Running via Spring preloader in process 33500
Run options: --seed 12040
# Running:
.
Finished in 0.407556s, 2.4537 runs/s, 7.3610 assertions/s.
1 runs, 3 assertions, 0 failures, 0 errors, 0 skips
But to run other test like place an order
, add a menu_item
i have to have user signed in 1st
So i created a helper file in helpers/helpers.rb
def signin
post "/users/",
params: { email: "test@gmail.com ", password: "test", role: "customer", name: "test_name" }
end
Also
def create_menu
post "/menus/",
params: { name: "test_menu" }
end
We also need ActiveMenu
and add MenuItem
ActiveMenu.create(active_menu: Menu.last.id)
MenuItem.create(menu_id: Menu.last.id, name: "name", description: "description", price: 45)
For creating the Order
another helper method
def create_order
new_order = Order.create(user_id: User.first.id, delivered_at: "", order_status: "cart")
new_order.id
end
and then a writing test for placing an order
require "test_helper"
require_relative "../helpers/helpers.rb"
class OrderItemsTest < ActionDispatch::IntegrationTest
test "can add order_items" do
signin()
create_menu()
ActiveMenu.create(active_menu: Menu.last.id)
MenuItem.create(menu_id: Menu.last.id, name: "name", description: "description", price: 45)
order_id = create_order()
assert_difference("OrderItem.count") do
post "/order_items/",
params: {
order_id: order_id,
menu_item_id: MenuItem.last.id,
menu_item_name: "Coffee",
menu_item_price: 40,
count: 1,
}
end
assert_response :redirect
follow_redirect!
assert_equal "/orders", path
end
end
Result
❯ bin/rails test test/integration/order_items_test.rb
Running via Spring preloader in process 33704
Run options: --seed 29784
# Running:
.
Finished in 0.990202s, 1.0099 runs/s, 3.0297 assertions/s.
1 runs, 3 assertions, 0 failures, 0 errors, 0 skips
Are tests similar to this?
Yes, they are and you've also touched a few issues which prevents you from writing tests which can be refactored similar to any other code we write.
fixtures
for your testing data. See: https://guides.rubyonrails.org/testing.html#the-low-down-on-fixturessetup
and teardown
to set the pre & post conditions for a test. So in setup
you can sign-in and in teardown
you can sign-out. For each test you need a blank slate. Otherwise it is possible that one of the previously run tests would put the data in a particular state, and subsequent tests could depend on that state instead of the one you expect. I am trying to create login
test
i created a users fixtures: users.yml
deep:
name: Deepankar Bhade
role: customer
email: deepankar@gmail.com
password_digest: deepankar
then a helper sigin()
def signin(user)
post "/users/",
params: { email: user.email, password: user.password_digest, role: user.role, name: user.name }
end
then a sessions_controller_test.rb
require "test_helper"
require_relative "../helpers/helpers.rb"
class SessionsControllerTest < ActionDispatch::IntegrationTest
setup do
# ? Register a new user
@user = users(:deep)
signin(users(:deep))
end
test "should login a registers user" do
post "/signin/",
params: { email: @user.email, password: @user.password_digest }
end
end
I haven't added any assert statement here as the test gives an error
❯ rails test test/controllers/sessions_controller_test.rb
Running via Spring preloader in process 41724
Run options: --seed 36581
# Running:
E
Error:
SessionsControllerTest#test_should_login_a_registers_user:
BCrypt::Errors::InvalidHash: invalid hash
app/controllers/sessions_controller.rb:9:in `create'
test/controllers/sessions_controller_test.rb:12:in `block in <class:SessionsControllerTest>'
rails test test/controllers/sessions_controller_test.rb:11
Finished in 0.406695s, 2.4588 runs/s, 0.0000 assertions/s.
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
what exactly am I doing wrong? 😅
Would create a PR on tests today
deep: ... password_digest: deepankar
Error: SessionsControllerTest#test_should_login_a_registers_user: BCrypt::Errors::InvalidHash: invalid hash
It looks like the password_digest
value in your fixture was rejected because its not a valid hash. You will need to pass a digest of the password deepankar
.
deep: ... password_digest: deepankar
Error: SessionsControllerTest#test_should_login_a_registers_user: BCrypt::Errors::InvalidHash: invalid hash
It looks like the
password_digest
value in your fixture was rejected because its not a valid hash. You will need to pass a digest of the passworddeepankar
.
I think this solves it :
password_digest: <%= BCrypt::Password.create('deepankar') %>
I tried some test
❯ rails test
Running via Spring preloader in process 54916
Run options: --seed 9308
# Running:
...........
Finished in 1.962253s, 5.6058 runs/s, 17.8366 assertions/s.
11 runs, 35 assertions, 0 failures, 0 errors, 0 skips
I would try to add a test to placing orders now :)
For a deployed application every modification introduces an element of risk. It could introduce unexpected behaviour. An existing feature could stop working. This is difficult to notice without tests. You may only find out when a user reports the bug in a live application.
You now have a working & live implementation of cafeman. This is a great point to start adding automated tests.
Rails has an excellent guide to get you started on testing here: https://guides.rubyonrails.org/testing.html You should add the following tests:
Note: Please ignore system testing in the documentation. You do not have to add these.
Since this is a new topic, feel free to ask lots of questions and discuss it 😃