Skip to content

Commit b95cf34

Browse files
authored
Add guide on writing good tests (#42)
1 parent 5be867b commit b95cf34

File tree

1 file changed

+70
-8
lines changed

1 file changed

+70
-8
lines changed

CONTRIBUTING.md

+70-8
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,85 @@ function sum(arr: number[]): number {
106106
```
107107

108108
- Avoid using global variables and avoid `==` (use `===` instead).
109-
- Use only `let` and `const`, never use `var`
109+
- Use only `let` and `const`, never use `var`; inline expressions which are only used a single time unless naming a variable adds to the readability.
110110
- Prefer proper input/output of your functions over side effects.
111111
- We required the use of TypeScript.
112112
- Only use `any` if appropriate. Prefer to create proper types instead.
113113
- No redundant naming. Don't prefix interfaces with `I`, class members with `m`, function with `func` or `f`, etc.
114114
- Prefer using optional fields over `null` or `undefined`.
115+
- Annotate arrays as `foos: Foo[]` instead of `foos: Array<Foo>`.
116+
- Refrain from importing external libraries. Implement the algorithms "from scratch".
117+
- Most importantly:
118+
- **Be consistent in the use of these guidelines when submitting.**
119+
- Happy coding!
120+
121+
##### Bad
115122

116123
```ts
117-
// BAD
118124
let foo = { x: 123, y: undefined };
125+
````
126+
127+
##### Good
119128

120-
// GOOD
129+
```ts
121130
let foo: { x: number, y?: number } = { x: 123 };
122131
```
123132

124-
- Annotate arrays as `foos: Foo[]` instead of `foos: Array<Foo>`.
125-
- Refrain from importing external libraries. Implement the algorithms "from scratch".
126-
- Most importantly:
127-
- **Be consistent in the use of these guidelines when submitting.**
128-
- Happy coding!
133+
#### Writing Good Tests
134+
135+
Trivial "algorithms" or formulas (think `abs`) may go without tests. Everything else **must** have decent test coverage.
136+
While it is not required that your tests trigger execution of every line of code you have written,
137+
you should definitely test edge cases, selected standard inputs, larger inputs and ideally even randomized inputs.
138+
139+
Tests are written using [Jest](https://jestjs.io/). If you can meaningfully divide your test cases into descriptive classes,
140+
use a `describe` block for the algorithm and `it` blocks for classes of test cases.
141+
If you can not classify your test cases (which is the case especially for trivial algorithms like Fibonacci numbers or factorials),
142+
use a single `test` block for all test cases. **Do not** use `describe` & `it` blocks with redundant descriptions for the `it` blocks:
143+
144+
##### Bad
145+
146+
```ts
147+
describe("Factorial", () => {
148+
// Bad: it-blocks add absolutely no value
149+
it("works", () => {
150+
expect(factorial(0)).toBe(1);
151+
});
152+
it("works #2", () => {
153+
expect(factorial(1)).toBe(1);
154+
});
155+
// Bad: Redundant it-block description
156+
it("3! is 6", () => {
157+
expect(factorial(3)).toBe(6);
158+
});
159+
// Bad: Redundant it-block description
160+
it("4! is 24", () => {
161+
// Bad: Naming these variables adds no value; they should have been inlined
162+
const input = 4;
163+
const expected = 24;
164+
expect(factorial(input)).toBe(expected);
165+
});
166+
});
167+
```
168+
169+
##### Good
170+
171+
```ts
172+
// Good: Much more concise, still the same coverage
173+
test("Factorial", () => {
174+
expect(factorial(0)).toBe(1);
175+
expect(factorial(1)).toBe(1);
176+
expect(factorial(3)).toBe(6);
177+
expect(factorial(4)).toBe(24);
178+
});
179+
```
180+
181+
##### Even Better
182+
183+
```ts
184+
// More concise, plus we get test name formatting
185+
test("Factorial", () => {
186+
test.each([[0, 1], [1, 1], [3, 6], [4, 24]])('%i! = %i', (n, expected) => {
187+
expect(factorial(n)).toBe(expected);
188+
});
189+
});
190+
```

0 commit comments

Comments
 (0)