Browse Source

Merge 2c139a075f into 4262b1c5b5

pull/3330/merge
Samuel Young 2 weeks ago committed by GitHub
parent
commit
ed42cd28c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      app/helpers/collection_time_helper.rb
  2. 78
      docs/testing/best_practice.md
  3. 43
      docs/testing/factories.md
  4. 34
      docs/testing/index.md

6
app/helpers/collection_time_helper.rb

@ -102,6 +102,10 @@ module CollectionTimeHelper
# useful for writing future tests that will also test the current time if it can or a future year if needed.
# stops tests being frozen on a specific year.
def collection_start_date_for_year_or_later(year)
collection_start_date_for_year([current_collection_start_year, year].max)
collection_start_date_for_year(collection_start_year_for_year_or_later(year))
end
def collection_start_year_for_year_or_later(year)
[current_collection_start_year, year].max
end
end

78
docs/testing/best_practice.md

@ -0,0 +1,78 @@
---
nav_order: 2
parent: Testing
---
# Testing best practice
Note many old tests on CORE don't follow these guidelines. Feel free to bring them up to code.
## CollectionTimeHelper
Very useful class containing lots of date helper methods. Overuse these.
## Year-specific tests
The following guidelines should create tests that are:
- Unlikely to break between years
- Clearly marked when year specific
- Test up to date code wherever possible
Note that guidelines are directed for the point in time after a new form build has been completed.
If you're currently in new form build and writing new tests, imagine that it is currently post release of the form and follow the guidance from there. This is so we can be happy tests will not break on release day as well.
- If writing a test that doesn't need to be year specific, use `current_collection_start_year` or `current_collection_start_date`.
- If writing a test for the past, use `collection_start_date_for_year(year)`, and mark the test with metadata: `{ year: xx }`.
- If writing a test for the present & future, use `collection_start_date_for_year_or_later(year)`, and mark the test with metadata: `{ year: xx }`.
We only maintain tests for years that are currently editable in CORE (usually this and last collection year). If you see a file that contains tests for years older, consider updating or removing them.
## let syntax
You will see many tests using the `let` syntax. For instance `let(:collection_year) { 2026 }`. These are used to define variables specific to a given test. When the variable `collection_year` is called for the first time, the code inside the block will be evaluated.
They are useful for test specific logic. You can define a `before` block in an outer context, and use `let` blocks in an inner context to define the variables used in that before block. This allows for all arrange logic to be written once, drawing from variables defined later in a more specific context.
`let` blocks will not be evaluated till then run in a test. If you need them to be evaluated immediately (say, an inner context uses time travel), define a `let!` block.
## context
Contexts group related tests. They can also define `before` blocks that run before all tests in the context, and set up specific variables using `let`. With proper setup, a series of contexts can do all the arranging tests will need. This means the final test `it` blocks only need to act and assert.
## Example
A test suite may look like
```ruby
describe "class" do
let(:dependent_object) { dependent_object(name: "test", year:) }
context "#method" do
before do
# do some setup with dependent_object and year
end
context "in 2025", metadata: { year: 25 } do
let(:year) { 2025 }
it "works" do
# act
# assert
end
end
context "in 2026 and later", metadata: { year: 26 } do
let(:year) { collection_start_year_for_year_or_later(2026) }
it "works also" do
# act
# assert
end
end
end
end
```

43
docs/testing.md → docs/testing/factories.md

@ -1,44 +1,15 @@
---
nav_order: 4
nav_order: 2
parent: Testing
---
# Testing
- We use [RSpec](https://rspec.info/) and [Capybara](https://teamcapybara.github.io/capybara/)
- Capybara is used for our feature tests. These use the Rack driver by default (faster) or the Gecko driver (installation required) when the `js: true` option is passed for a test.
- Capybara is configured to run in headless mode but this can be toggled by commenting out `app/spec/rails_helper.rb#L14`
- Capybara is configured to use Gecko driver for JavaScript tests as Chrome is more commonly used and so naturally more likely to be better tested but this can be switched to Chrome driver by changing `app/spec/rails_helper.rb#L13`
- Feature specs are generally written sparingly as they’re also the slowest, where possible a request spec is preferred as this still tests a large surface area (route, controller, model, view) without the performance impact. They are not suitable for tests that need to run JavaScript or test that a specific set of interaction events that trigger a specific set of requests (with high confidence).
- Test data is created with [FactoryBot](https://github.com/thoughtbot/factory_bot) where ever possible
## Parallel testing
- The RSpec test suite can be ran in parallel in local development for quicker turnaround times
- Setup with the following:
```sh
bundle exec rake parallel:setup
```
- Run with:
```sh
RAILS_ENV=test bundle exec rake parallel:spec
```
## Factories for Lettings Log, Sales Log, Organisation, and User
# Factories for Lettings Log, Sales Log, Organisation, and User
Each of these factories has nested relationships and callbacks that ensure associated objects are created and linked properly. For instance, creating a `lettings_log` involves creating or associating with a `user`, which in turn is linked to an `organisation`, potentially leading to creating `organisation_rent_periods` and a `data_protection_confirmation`.
This documentation outlines the objects that are created and/or persisted to the database when using FactoryBot to create or build models for LettingsLog, SalesLog, Organisation, and User. There are other factories, but they are simpler, less frequently used and don't have as much resource hierarchy.
### Lettings Log
## Lettings Log
Objects Created/Persisted:
@ -53,7 +24,7 @@ Example Usage:
let(:lettings_log) { create(:lettings_log) }
```
### Sales Log
## Sales Log
Objects Created/Persisted:
@ -67,7 +38,7 @@ Example Usage:
let(:sales_log) { create(:sales_log) }
```
### Organisation
## Organisation
Objects Created/Persisted:
@ -81,7 +52,7 @@ Example Usage:
let(:organisation) { create(:organisation, rent_periods: [1, 2])}
```
### User
## User
Objects Created/Persisted:

34
docs/testing/index.md

@ -0,0 +1,34 @@
---
has_children: true
nav_order: 4
---
# Testing
- We use [RSpec](https://rspec.info/) and [Capybara](https://teamcapybara.github.io/capybara/)
- Capybara is used for our feature tests. These use the Rack driver by default (faster) or the Gecko driver (installation required) when the `js: true` option is passed for a test.
- Capybara is configured to run in headless mode but this can be toggled by commenting out `app/spec/rails_helper.rb#L14`
- Capybara is configured to use Gecko driver for JavaScript tests as Chrome is more commonly used and so naturally more likely to be better tested but this can be switched to Chrome driver by changing `app/spec/rails_helper.rb#L13`
- Feature specs are generally written sparingly as they’re also the slowest, where possible a request spec is preferred as this still tests a large surface area (route, controller, model, view) without the performance impact. They are not suitable for tests that need to run JavaScript or test that a specific set of interaction events that trigger a specific set of requests (with high confidence).
- Test data is created with [FactoryBot](https://github.com/thoughtbot/factory_bot) where ever possible
# Parallel testing
- The RSpec test suite can be ran in parallel in local development for quicker turnaround times
- Setup with the following:
```sh
bundle exec rake parallel:setup
```
- Run with:
```sh
RAILS_ENV=test bundle exec rake parallel:spec
```
Loading…
Cancel
Save