|
| 1 | +## Running Tests |
| 2 | + |
| 3 | +We use vitest exclusively for testing. To execute tests for a particular workspace, run the following command: |
| 4 | + |
| 5 | +```bash |
| 6 | +pnpm run test --filter webapp |
| 7 | +``` |
| 8 | + |
| 9 | +Prefer running tests on a single file (and first cding into the directory): |
| 10 | + |
| 11 | +```bash |
| 12 | +cd apps/webapp |
| 13 | +pnpm run test ./src/components/Button.test.ts |
| 14 | +``` |
| 15 | + |
| 16 | +If you are cd'ing into a directory, you may have to build dependencies first: |
| 17 | + |
| 18 | +```bash |
| 19 | +pnpm run build --filter webapp |
| 20 | +cd apps/webapp |
| 21 | +pnpm run test ./src/components/Button.test.ts |
| 22 | +``` |
| 23 | + |
| 24 | +## Writing Tests |
| 25 | + |
| 26 | +We use vitest for testing. We almost NEVER mock anything. Start with a top-level "describe", and have multiple "it" statements inside of it. |
| 27 | + |
| 28 | +When writing anything that needs redis or postgresql, we have some internal "testcontainers" that are used to spin up a local instance, redis, or both. |
| 29 | + |
| 30 | +redisTest: |
| 31 | + |
| 32 | +```typescript |
| 33 | +import { redisTest } from "@internal/testcontainers"; |
| 34 | +import { createRedisClient } from "@internal/redis"; |
| 35 | + |
| 36 | +describe("redisTest", () => { |
| 37 | + redisTest("should use redis", async ({ redisOptions }) => { |
| 38 | + const redis = createRedisClient(redisOptions); |
| 39 | + |
| 40 | + await redis.set("test", "test"); |
| 41 | + const result = await redis.get("test"); |
| 42 | + expect(result).toEqual("test"); |
| 43 | + }); |
| 44 | +}); |
| 45 | +``` |
| 46 | + |
| 47 | +postgresTest: |
| 48 | + |
| 49 | +```typescript |
| 50 | +import { postgresTest } from "@internal/testcontainers"; |
| 51 | + |
| 52 | +describe("postgresTest", () => { |
| 53 | + postgresTest("should use postgres", async ({ prisma }) => { |
| 54 | + // prisma is an instance of PrismaClient |
| 55 | + }); |
| 56 | +}); |
| 57 | +``` |
| 58 | + |
| 59 | +containerTest: |
| 60 | + |
| 61 | +```typescript |
| 62 | +import { containerTest } from "@internal/testcontainers"; |
| 63 | + |
| 64 | +describe("containerTest", () => { |
| 65 | + containerTest("should use container", async ({ prisma, redisOptions }) => { |
| 66 | + // container has both prisma and redis |
| 67 | + }); |
| 68 | +}); |
| 69 | +``` |
| 70 | + |
| 71 | +## Dos and Dont's |
| 72 | + |
| 73 | +- Do not mock anything. |
| 74 | +- Do not use mocks in tests. |
| 75 | +- Do not use spies in tests. |
| 76 | +- Do not use stubs in tests. |
| 77 | +- Do not use fakes in tests. |
| 78 | +- Do not use sinon in tests. |
| 79 | +- Structure each test with a setup, action, and assertion style. |
| 80 | +- Feel free to write long test names. |
| 81 | +- If there is any randomness in the code under test, use `seedrandom` to make it deterministic by allowing the caller to provide a seed. |
0 commit comments