You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: developer_docs/testing.md
+79-73Lines changed: 79 additions & 73 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,8 +58,9 @@ Find more commands in the [Jest documentation](https://jestjs.io/docs/cli).
58
58
## Why write tests
59
59
- Good place to start if you're learning the codebase because it's harder to mess up production code
60
60
- Benefits all future contributors by allowing them to check their changes for errors
61
-
-Catches easy-to-miss errors
61
+
-Increased usage: Most code with only ever have a single invocation point, but this means that code might not be particularly robust and lead to bugs if a different devleoper reuses it in a different context. Writing tests increases the usage of the code in question and may improve the long-term durability, along with leading developers to refactor their code to be more usable. [[3]](#References)
62
62
- Lets you check your own work and feel more comfortable sumbitting PRs
63
+
- Catches easy-to-miss errors
63
64
- Good practice for large projects
64
65
- Many of the existing components don't have tests yet, and you could write one :-)
65
66
@@ -71,30 +72,62 @@ When you modify an existing component, it's a good idea to run the test suite to
71
72
72
73
## Writing a test
73
74
Want to get started writing a test for a new file or an existing file, but not sure how?
75
+
76
+
74
77
### For React components
75
-
(the below assumes we're using proposed folder structure 1)
76
-
1. Make a new file in the ``__tests__`` folder that's directly adjacent to your file. For example, if ``example.jsx`` is in ``src/components``, then you would make a file called ``example.test.jsx`` in ``src/components/__tests__``
78
+
1. Make a new file directly adjacent to your file. For example, if ``example.jsx`` is ``src/components/example.jsx``, then you would make a file called ``example.test.jsx`` at ``src/components/example.test.jsx``
77
79
2. Check if the component is connected to redux or not.
78
80
3. If it is, see the [redux section](#Testing-Redux) below on how to write tests for that.
79
81
4. If it's not, see the [section below on writing tests for unconnected components](#Testing-plain-components).
80
-
5. If you're testing UI elements, there are many ways of querying for them, but you can add a data-testid attribute to the component in the source code and use ``getByTestId("testid")`` to retrieve it.
81
82
)
83
+
5. "Arange, Act, Assert:" In other words, *arrange* the set up for the test, *act* out whatever the subject's supposed to do, and *assert* on the results. [[3]](#References)
84
+
85
+
### In every test file
86
+
Maybe we want to add these as comments??
87
+
- What behavior is and isn't covered by the suites What dependencies should be replaced with mocks and what should be left realistic
88
+
- The primary design benefit (if any) of these tests
89
+
- The primary regression protection (if any) provided by these tests
90
+
- What an example test should look like
91
+
- The maximum permissible elapsed time for a run of an individual test or for the full suit
92
+
93
+
### Consistency across tests
94
+
> "Teams that adopt a rigid and consistent structure to each test tend to more readily understand each test, because every deviation from the norm can be trusted to be meaningful and somehow specific to the nature of the subject."
95
+
- We want to default to using meaningless test data stored in the redux-test-stores folder.
96
+
- Be sure to follow the folder structure
97
+
- Follow the rendering guidelines set up for the components in this README.
98
+
99
+
### Querying for elements
100
+
Read about the recommended order of priority for queries in [the testing library docs](https://testing-library.com/docs/guide-which-query/#priority). We recommend using roles and text, or labels. You can use this [handy extension](https://chrome.google.com/webstore/detail/testing-playground/hejbmebodbijjdhflfknehhcgaklhano/related) to do this.
101
+
82
102
83
103
### What to test
84
104
For any type of component, you might want to consider testing:
85
-
- User input results in the class's method being called.
86
-
```js
87
-
//component is the return value of calling render()
- The text or divs that you expect to be on the page are actually there.
105
+
- The text or divs that you expect to be on the page are actually there. You can use [Queries](https://testing-library.com/docs/queries/about/) for this.
95
106
- a previously saved snapshot of the HTML matches a snapshot taken during testing.
96
107
- what else?? help!
97
108
109
+
>Only test the behaviors you know you need to care about. For example, if the desired behavior of a particular edge case doesn't truly matter yet or isn't fully understood, don't write a test for it yet. Doing so would restrict the freedom to refactor the implementation. Additionally, it will send the signal to future readers that this behavior is actually critical, when it very well might not be (perhaps a form of [accidental creativity]()). [[3]](#References)
110
+
111
+
**Don't test unreachable edge cases:** You would have to add code to your original implementation to guard against these cases. The future proofing and the added cost to the codebase "is generally not worth their preceived potential benefits" [[3]](#References)
112
+
113
+
**Make sure your tests are sufficient:** You want to make sure your test actually specifies all the behaviors you want to ensure the code exhibits. For example, testing that ``1+1 > 0`` would be correct, but insufficient. [[3]](#References)
114
+
115
+
### File structure
116
+
Each test should have a top-level ```describe`` block to group related blocks together, with the name of the component under test.
117
+
*example.test.ts*
118
+
119
+
```js
120
+
importexamplefrom'./example';
121
+
122
+
describe('example', () => {
123
+
it('creates a new example', () => {
124
+
//your tests here
125
+
});
126
+
});
127
+
128
+
```
129
+
130
+
98
131
### For Redux action creators or reducers
99
132
See the [redux section](#Testing-Redux) below :)
100
133
@@ -116,58 +149,8 @@ You can also see it used in the context of a test [in the SketchList.test.jsx fi
116
149
117
150
## Files to be aware of
118
151
119
-
### Proposed folder structure 1
120
-
All tests in``__tests__`` folders that are directly adjacent to the files that they are testing. For example, if you're testing ``examplefolder/Sketchlist.test.jsx``, the test would be in ``examplefolder/__tests__/Sketchlist.test.jsx``. This is so that the tests are close to the files they're testing but are still hidden away from view most of the time. This also means that any snapshot files will be stored in the testing folder, such as ``examplefolder/__tests__/__snapshots__/Sketchlist.test.jsx.snap``
121
-
122
-
Manual mocks are in``__mocks__`` folders are adjacent to the modules that they're mocking.
123
-
124
-
Note: Even if you mock a user module in a ``__mocks__`` folder, user modules have to be explictly mocked in the test too, with ``Jest.mock("path_to_module")``
125
-
126
-
Node modules are mocked in the ``__mocks__`` folder at the root of the client folder, which also includes any mocks that are needed for user modules at the root of the folder directory.
127
-
128
-
```
129
-
.
130
-
└── client
131
-
├── __mocks__
132
-
│ ├── axios.js
133
-
| ├── i18n.js
134
-
| └── ...other Node modules you want to mock
135
-
├── modules
136
-
│ ├── IDE
137
-
│ │ ├── actions
138
-
│ │ │ ├── __mocks__
139
-
│ │ │ │ ├── projects.js
140
-
│ │ │ │ └─ ... other action creator mocks
141
-
│ │ │ ├── __tests__
142
-
│ │ │ │ ├── projects.test.js
143
-
│ │ │ │ └─ ... other redux action creator tests
144
-
│ │ │ └── ... action creators
145
-
│ │ ├── components
146
-
│ │ │ ├── __tests__
147
-
│ │ │ │ ├── __snapshots__
148
-
│ │ │ │ │ ├── SketchList.test.jsx.snap
149
-
│ │ │ │ │ └─ ... other snapshots
150
-
│ │ │ │ ├── SketchList.test.jsx
151
-
│ │ │ ├── SketchList.test.jsx
152
-
│ │ │ └── ... and more component files
153
-
│ │ ├── reducers
154
-
│ │ │ ├── __tests__
155
-
│ │ │ │ ├── assets.test.js
156
-
│ │ │ │ └─ ... other reducer tests
157
-
│ │ │ ├── assets.js
158
-
│ │ │ └── ...more reducers
159
-
│ └── ... more folders
160
-
├── redux_test_stores
161
-
| ├── test_store.js
162
-
│ └── ...any other redux states you want to test
163
-
├── i18n-test.js
164
-
├── jest.setup.js
165
-
├── test-utils.js
166
-
└──... other files and folders
167
-
```
168
-
169
-
### Proposed folder structure 2
170
-
All tests are directly adjacent to the files that they are testing. For example, if you're testing ``examplefolder/Sketchlist.test.jsx``, the test would be in``examplefolder/Sketchlist.test.jsx``. This is so that the tests are as close as possible to the files. This also means that any snapshot files will be stored in the same folder, such as ``examplefolder/__snapshots__/Sketchlist.test.jsx.snap``
152
+
### Folder structure
153
+
All tests are directly adjacent to the files that they are testing, as described in the [React docs](https://reactjs.org/docs/faq-structure.html#grouping-by-file-type). For example, if you're testing ``examplefolder/Sketchlist.test.jsx``, the test would be in ``examplefolder/Sketchlist.test.jsx``. This is so that the tests are as close as possible to the files. This also means that any snapshot files will be stored in the same folder, such as ``examplefolder/__snapshots__/Sketchlist.test.jsx.snap``
171
154
172
155
Manual mocks are in``__mocks__`` folders are adjacent to the modules that they're mocking.
173
156
@@ -331,7 +314,7 @@ Consider what you want to test. Some possible things might be:
331
314
- User input results in the expected function being called with the expected argument.
@@ -446,29 +429,52 @@ A few components also import ``./client/i18n.js`` (or ``./client/utils/formatDat
446
429
447
430
## Some more background on tests
448
431
449
-
### test driven development (TDD)
450
-
BDD???
432
+
### Test Driven Development (TDD)
433
+
Do we want a section here about TDD history?
451
434
452
435
### snapshot testing
453
436
You can save a snapshot of what the HTML looks like when the component is rendered.
454
437
455
438
### integration tests
456
-
Testing multiple components together. A small example is rendering a parent component and a child component within that.
439
+
Testing multiple components together. A small example is rendering a parent component in order to test the interactions between children components. For frontend development, integration tests might focus on end-to-end flows using Puppeter or another type of headless browser testing. We don't do this just yet.
457
440
458
441
### unit tests
459
-
Most of our tests are of this type. In this, you're testing a the functionality of a single component and no more.
442
+
Most of our tests are of this type. In this, you're testing a the functionality of a single component and no more. They provide lots of feedback on the specific component that you're testing, with the cost of high [redundant coverage](https://github.com/testdouble/contributing-tests/wiki/Redundant-Coverage) and more time spent refactoring tests when components get rewritten.
443
+
444
+
### Other terminology for mocking
445
+
Thanks [Test Double Wiki](https://github.com/testdouble/contributing-tests/wiki/Test-Double) for the definitions.
446
+
#### Test double
447
+
Broadest available term to describe any fake thing used in place of a real thing for a test.
448
+
#### Stub
449
+
Any test double that uses a preconfigured response, such always responding with placeholder json to a certain fetch call.
450
+
#### Fake
451
+
A test double that provides an alternate implementation of a real thing for the purpose of a test.
452
+
#### Mock
453
+
Colloquially can mean any of the above, just used generally for test doubles.
454
+
#### Partial mock
455
+
Refers to any actual object which has been wrapped or changed to provide artificial responses to
456
+
some methods but not others. Partial mocks are widely considered to be an anti-pattern of test double usage.
457
+
458
+
#### Spy
459
+
Records every invocation made against it and can verify certain interactions took place after the fact.
460
460
461
461
## Internationalization
462
462
This project uses i18next for internationalization. If you import the render function with the i18n wrapper from ``test_utils.js``, it's set up to use English, so the components with be rendered with English text and you should be able to count on this to test for specific strings.
463
463
464
464
## Tips
465
465
1. Make test fail at least once to make sure it was a meaningful test
466
466
2. "If you or another developer change the component in a way that it changes its behaviour at least one test should fail." - [How to Unit Test in React](https://itnext.io/how-to-unit-test-in-react-72e911e2b8d)
467
+
3. Avoid using numbers or data that seem "special" in your tests. For example, if you were checking the "age" variable in a component is a integer, but checked it as so ``expect(person.ageValidator(18)).toBe(true)``, the reader might assume that the number 18 had some significance to the function because it's a significant age. It would be better to have used 1234.
467
468
468
469
## More Resources
469
-
- any other resources for learning about tests here?
1. [Best practices for unit testing with a react redux approach](https://willowtreeapps.com/ideas/best-practices-for-unit-testing-with-a-react-redux-approach)
473
474
474
-
2. [How to test your react-redux application (this article also references axios)](https://medium.com/asos-techblog/how-to-test-your-react-redux-application-48d90481a253)
475
+
2. [How to test your react-redux application (this article also references axios)](https://medium.com/asos-techblog/how-to-test-your-react-redux-application-48d90481a253)
476
+
477
+
3. [Testing Double Wiki (Special thanks to this wiki for being such a comprehensive guide to the history of testing and best practices.)](https://github.com/testdouble/contributing-tests/wiki/Tests%27-Influence-on-Design)
478
+
479
+
## Special thanks
480
+
Thank you to HipsterBrown for helping us out with writing this documentation.
0 commit comments