事の発端
TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング を見てからTDDに興味津々です。
というか、長い間開発やってるのだから、この辺もちゃんと出来ないとだめだと思って勉強中です。
今回のターゲット
- 現在社内で構築しているbackendをTDDできるようにする
主な環境
- express
- jest
- typescript
- typeorm
- mariadb
一応、全部コンテナで実行できるようになっています。(ハズ)
詳細はこちらを参照
準備
自分は最近、npmでは無くyarn を使用しているので、以降すべてyarn を
使用することを前提に説明していきます。
ディレクトリの構成は主に以下のような感じです。
.
├── package.json
├── src
│ ├── entity
│ │ └── User.ts
│ ├── index.ts
│ ├── migration
│ └── server.ts
└── test
└── server.spec.ts
必要なパッケージのインストール
多分、以下のパッケージを入れておけば良いのかと。
自分の場合は、ORMとしてtypeormを使っているので、typeormもインストールし
プロジェクトの作成もしています。
$ yarn global add typeorm
$ typeorm init --name app --database mysql
$ cd app
$ yarn add \
@types/express \
@types/express-session \
@types/jest \
@types/node \
@types/supertest \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
cors \
eslint \
eslint-config-prettier \
eslint-plugin-prettier \
express \
express-session \
jest \
mysql2 \
prettier \
reflect-metadata \
supertest \
ts-jest \
ts-node \
tsconfig-paths \
typescript
express サーバの作成
まずはテストしやすいようにexpressのサーバを切り出します。
import express from "express";
export class AppServer {
public app: express.Application;
constructor() {
this.app = express();
this.setupRoutes();
}
public setupRoutes() {
this.app.get("/", (req, res) => {
res.json({ message: "AppServer started" });
});
}
public start() {
this.app.listen( {port: 4000}, () => {
console.log(`server on http://localhost:4000`);
});
}
}
package.json を修正
「yarn test」でテストを実行できるようにpackage.json を修正。
"scripts": {
- "start": "ts-node src/index.ts"
+ "start": "ts-node src/index.ts",
+ "test": "jest"
},
jest の設定を何もしてないと以下のように「import」が使えないとエラーを
出すので、jestでtypescriptのソースを解釈できるように以下のように追記します。
自分の場合、テストコードは「test」ディレクトリに保存し、命名規則的には「〜.spec.ts」に
しているため、「testMatch」の部分にその旨を設定します。
Cannot use import statement outside a module
"scripts": {
"start": "ts-node src/index.ts",
"test": "jest"
- }
+ },
+ "jest": {
+ "moduleFileExtensions": [
+ "ts",
+ "js"
+ ],
+ "transform": {
+ "^.+\\.ts$": "ts-jest"
+ },
+ "globals": {
+ "ts-jest": {
+ "tsConfig": "tsconfig.json"
+ }
+ },
+ "testMatch": [
+ "**/test/**/*.spec.ts"
+ ]
+ }
tsconfig.json を修正
「export default〜」で定義された定義をimportできるようにするため、
tsconfig.json に以下を追記します。
※ 認識あっているんだろうか?
{
"compilerOptions": {
"lib": [
"es5",
"es6"
],
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./build",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
+ "esModuleInterop": true,
"sourceMap": true
}
}
ここまでで設定関連は終了のはず。
テストソースを準備する
とりあえずbackend サーバとしては、GET で「/」にアクセスすると
「{message: "AppServer started"}」を返すようになっているため、
ステータスコード200を受けて、messageを正しく取得出来ているかのテストを準備します。
express をユニットテストする際には、どうもsupertest なるモジュールを使用するようなので、
こちらを使用します。
※ express のテストがこうだったし、他を探してもコレが一般的なのかと今の所思っています。
import request from "supertest";
import { AppServer } from "../src/server";
describe("GET /", () => {
it("return 200 and correct message", () => {
const server = new AppServer();
return request(server.app)
.get("/")
.expect(200)
.expect({message: "AppServer started"});
});
});
テストの実行
「yarn test」を実行してテストがパスすることを確認します。
今回は全部がコンテナ内で動作できるようにしているため、
以下を実行すればできるはずです。
$ git clone git@github.com:shun/tdd-express-typescript.git
$ cd tdd-express-typescript
$ docker-compose pull # 必要に応じて
$ docker-compose up -d
$ docker-compose exec -u node express bash
node@b51cacc0699d:~/app$ yarn test
yarn run v1.22.4
warning package.json: No license field
$ jest
PASS test/server.spec.ts
GET /
✓ return 200 and correct message (34 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.998 s
Ran all test suites.
Done in 3.71s.
これでやっとスタート地点に立てたかなと。。。
後は、これにtypeormでDBにアクセスしてデータを入れたり、取得したりすれば
思ったようなTDDができるはず。
これからTDDがんばるぞー。
長くなりましたが、ここまでお付き合いしていただきありがとうございます。