본문 바로가기

project

Final Project: 1주차 (testcase 환경설정)

typescript, typeORM 초기 환경설정을 한 후 필요한 api들 몇가지를 정의했다.

진행상황을 확인한 기업에서 testcase를 작성해보는것이 어떠냐고 제안을 해주셨다.

이미 작성되어있는 testcase들을 통과하기위해 각각의 유닛테스트의 내용을 자세히 살펴본적은 많지만, 어떻게 우리가 작성한 코드들과 연결이 되고, 어떤 흐름으로 테스트가 돌아가는지에 대해 자세히 공부해본적은 없어서 그럴 수 있는 좋은 기회인것 같아 도전해보겠다고 했다.

 

테스트 프레임워크/라이브러리는 해당 기업에서도 사용하고 있다는 mocha/chai 를 사용하기로 했다.

먼저 다음과 같은 package들을 설치했다

 

npm install -D mocha chai @types/mocha @types/chai
npm install ts-node

 

다음으로 src/test/server.spec.ts파일에 다음과 같은 코드를 작성하였다.

 

import * as chai from "chai";
import "mocha";
const expect = chai.expect;

describe("Implemented testcase", () => {
    it('should always pass', function () {
        expect(true).to.equal(true);
    });
});

 

test를 실행하기 위해 package.json 파일에 다음과 같은 sciprts를 추가해준다.

 

"scripts": {
	...
    "test": "mocha -r ts-node/register src/test/**/*.spec.ts --exit",
    ...
  }

 

이후에 npm test를 하면 테스트가 통과된것을 확인 할 수 있다.

 

여기까지는 그냥 mocha와 chai를 사용하여 테스트를 할 수 있는 환경을 설정했다면, 이제부터는 실제로 내가 작성한 코드들과 연결되는 부분들을 설정해주어야 한다.

여기부터 많은 의문들이 들었다.

1. test를 실행할때 어떻게 자동으로 서버가 구동되어서 동작하게 할까?

2. 유닛 테스트마다 스키마를 초기화해주어야 할것 같은데 어떻게 하지?

3. 스키마를 초기화해야한다면, 실제로 우리가 사용할 db와는 다른 test전용 db가 필요할것 같은데, 어떻게 script명령어에 따라 다르게 연결되도록 설정하지?

등등이 있었던 것 같다.

 

먼저 1번 질문에 대한 답을 다음과 같은 패키지를 이용하면 가능할 것 같았다.

 

npm install -D chai-http @types/chai-http

 

하지만 여기서 또 부딫힌 문제는 이전 포스팅에서 작성해놓은 app.ts파일의 코드들을 보면

src/app.ts

 

import * as express from "express";
import {Request, Response} from "express";
import * as bodyParser from  "body-parser";
import {createConnection} from "typeorm";
import {User} from "./entity/User";

// create typeorm connection
createConnection().then(connection => {
    const userRepository = connection.getRepository(User);

    // create and setup express app
    const app = express();
    app.use(bodyParser.json());

    // register routes
    ...
    ...

    // start express server
    app.listen(3000);
});

 

위와 같이 되어있어서 밑의 테스트코드 파일에서처럼 app.ts를 import해올수가 없을것 같다는 생각이였다.

src/test/server.spec.ts

 

import * as chai from "chai";
import "mocha";
import chaiHttp = require("chai-http");
import app from "app.ts파일 경로";
chai.use(chaiHttp);
const expect = chai.expect;

describe("Implemented testcase", () => {
    it('should always pass', function () {
        expect(true).to.equal(true);
    });
});

 

그것과 동시에 위의 3번질문에 대한 답을 찾아 헤매다가 NODE_ENV라는 것에 대해 알게 되었다.

NODE_ENV 값으로 배포/ 개발/ 테스트 환경 등등을 따로따로 설정하여 script를 실행시킬 수 있었다.

먼저 package.json의 scripts에 적용한 부분이다.

 

"scripts": {
	...
    "test": "NODE_ENV=test mocha -r ts-node/register src/test/**/*.spec.ts --exit",
    "dev": "NODE_ENV=development nodemon src/app.ts",
    "start": "NODE_ENV=production nodemon dist/app.js"
    ...
  },

 

터미널에 script명령어를 치면 다음과 같은 동작이 일어난다.

1. npm test : 'test'환경으로 mocha 테스트가 실행된다.

2. npm dev: 'development' 환경으로 app.ts파일을 실행시킨다.

3. npm start: 'production'환경으로 typescript를 javascript로 컴파일한 파일들이 저장되어있는 dist폴더의 app.js를 실행시킨다

위의 scripts에서 NODE_ENV='환경이름' 부분에서 환경이름은 다른 파일들에서 process.env.NODE_ENV 라는 이름으로 접근할 수 있다.

 

NODE_ENV에 맞게 ormconfig.json파일을 수정한 부분이다.

 

[
  {
    "name": "development",
    "type": "mysql",
    "host": "localhost",
    "port": 3306,
    "username": "root",
    "password": "자신의 mysql password",
    "database": "dogmate_dev",
    "entities": ["src/entity/*.ts"],
    "logging": true,
    "synchronize": true
  },
  {
    "name": "test",
    "type": "mysql",
    "host": "localhost",
    "port": 3306,
    "username": "root",
    "password": "자신의 mysql password",
    "database": "dogmate_test",
    "entities": ["src/entity/*.ts"],
    "logging": false,
    "synchronize": true,
    "dropSchema": true
  },
  {
    "name": "production",
    "type": "mysql",
    "host": "localhost",
    "port": 3306,
    "username": "root",
    "password": "자신의 mysql password",
    "database": "dogmate",
    "entities": ["dist/entity/*.js"],
    "logging": false,
    "synchronize": true
  }
]

 

이 설정이후에는 script명령어에 따라

npm start : dogmate라는 db에 연결

npm run dev: dogmate_dev라는 db에 연결

npm test: dogmate_test라는 db에 연결

이 된다.

 

test 파일에서 app을 import해올 수 있도록, 그리고 테스트를 실행할때 서버가 켜지고, db와 연결이 된 후에 유닛테스트들로 넘어갈 수 있도록(동기적으로 동작하도록) 하기 위해 utils라는 폴더에 NODE_ENV에 따라 db와의 연결을 설정해줄 수 있는 함수를 만들어 주고 app.ts와 test파일에 적용해보았다.

 

/src/utils/createTypeormConnection.ts

 

import { createConnection, getConnectionOptions } from "typeorm";

export const createTypeormConnection = async () => {
  const connectionOptions = await getConnectionOptions(process.env.NODE_ENV);
  return createConnection({ ...connectionOptions, name: "default" });
};

 

/src/app.ts

 

import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import { createTypeormConnection } from "./utils/createTypeormConnection";
// import adminRouter from "./routes/admin";
// import userRouter from "./routes/user";

const app = express();
const PORT: number = 3002;
app.use(bodyParser.json());
app.use(cors());

if (process.env.NODE_ENV !== "test") {
  createTypeormConnection();
}

// app.use("/api/user", userRouter);
// app.use("/api/admin", adminRouter);

// start express server
app.listen(PORT, async () => {
  console.log(`app is listening in port ${PORT}`);
});

export default app;

 

src/test/server.spec.ts

 

import * as chai from "chai";
import "mocha";
import chaiHttp = require("chai-http");
import app from "../app";
chai.use(chaiHttp);
const expect = chai.expect;
import { createTypeormConnection } from "../utils/createTypeormConnection";
import { Events } from "../entity/Events";
import { getRepository, getConnection } from "typeorm";

describe("Implemented testcase", () => {
  before(async () => {
    await createTypeormConnection();   // db와 연결이 완료되고나서 밑의 코드들이 실행됨
  });
  afterEach(async () => {
    const repository = await getRepository(Events);
    await repository.query(`TRUNCATE TABLE events;`);  // 유닛테스트 종료될때마다 테이블 초기화
  });
});

 

이제 필요한 테스트케이스들을 작성할 수 있게 되었다.

'project' 카테고리의 다른 글

Final Project 3주차 (typeorm-seeding)  (0) 2020.03.28
Final Project: 2주차 (Deploy)  (0) 2020.03.21
Final Project: 2주차 (multer-s3)  (0) 2020.03.21
Final Project: 1주차 (typeORM 초기환경 설정)  (0) 2020.03.15
First Project : My Type  (0) 2020.03.07