-
Notifications
You must be signed in to change notification settings - Fork 19
Backend Pattern Test
Caseflow includes three kinds of tests that are subdivided into folders.
spec/
- Keep tests fast.
- Don't use the DB if you don't have to.
- Prefer the FactoryBot
build_stubbed
method. - Don't write a feature spec if you're not testing user-facing changes.
- Don't write a feature spec for every scenario.
- Don't rely on order in tests.
- Don't create more entries in the DB than necessary.
- Avoid
allow_any_instance_of
andexpect_any_instance_of
1 - Group tests that require the same setup with
aggregate_failures
metadata - Prefer using
let
vsbefore
- https://www.betterspecs.org
It is not guaranteed that the order in which you create factories will be the same order in the result.
Examples:
-
Testing that a DB query sorts results by
created_at
or some other timestamp. Don't assume that if you create 2 factories in the test, the first one will always come first. Instead, specify a specific timestamp for each factory to ensure the test will be idempotent. -
Testing that the JSON rendered by the controller has certain attributes for some of the entries. Don't assume that if you create multiple factories, the JSON will return them in the same order. Instead of doing something like this:
create(:hearing) create(:hearing) hearings = JSON.parse(response.body)["hearings"] expect(hearings[0]["judge_last_name"]).to eq "Smith"
do this instead:
first_hearing = create(:hearing) hearings = JSON.parse(response.body)["hearings"] first_hearing_result = hearings.find { |hash| hash["id"] == first_hearing.id } expect(first_hearing_result["judge_last_name"]).to eq "Smith"
Setup for tests occupies a significant amount of time in Caseflow. If you have a group of tests for a particular subject
, you can use aggregate_failures
to avoid the cost of redundant setup time: 2
This:
it { expect(subject.status).to eq 200 }
it { expect(JSON.parse(subject.body)["veteran"]["email_address"]).to eq "[email protected]" }
it { expect(JSON.parse(subject.body)["veteran"]["full_name"]).to eq "Test User" }
can become:
it "returns expected response", :aggregate_failures do
expect(subject.status).to eq 200
expect(JSON.parse(subject.body)["veteran"]["email_address"]).to eq "[email protected]"
expect(JSON.parse(subject.body)["veteran"]["full_name"]).to eq "Test User"
end
The test-prof
gem also has a RuboCop that can automatically apply this pattern to some of our tests. You can enable this in your development environment by modifying the .rubocop.yml
file as described. Unfortunately, this can't be enabled in Code Climate because they do not allow installing of gems.