gpx2czml(2) - Typescript로 karma 테스트 하기

January 10, 2018

  • javascript를 typescript로 변경하기 위한 1일차 포스팅은 여기 를 참고해 주세요 :)

Typescript로 만들어진 코드를 karma로 테스트 하고 싶다!

이제 개발에 대한 환경은 대략적으로 구축이 되었습니다. (비록 약소하긴 하나..) 이제 karma와 mocha로 이전에 테스팅했던 부분들을 typescript 테스팅으로 바꾸고 싶었습니다. 물론, TDD, BDD 등 테스트 주도 환경을 완벽하게 구현해 내시는 고수분들도 많으시나.. 저는 그 실력까지는 못가더라도, 개발중에 간간히 테스트 환경을 구축해서 해보려고 노력하고 있습니다 ㅠㅠ

제가 주로 쓰는 framework는 Karma에 mocha를 얹어서 사용하며, sinon, chai등과 should 플러그인을 사용하려고 하고 있습니다. 아예 바꾸는겸 테스트 환경도 typescript로 전체 다 바꾸려고 합니다.

npm으로 설치부터..

karma에서 사용하는 브라우저를 처음에는 chrome으로 설정했으나, phantomjs로 바꾸고자 했습니다. (은근히 새창뜨는게 짜증나더라구요;;) karma부터 다 설치를 해주는것이 좋겠습니다.

npm install karma karma-mocha karma-webpack karma-phantomjs-launcher karma-spec-reporter karma-verbose-reporter karma-phantomjs-shim karma-sourcemap-loader karma-chai --save-dev

이 중에 karma-verbose-reporter는 terminal 창에 상세 테스트에 대한 결과를 출력하기 위해서 사용했습니다. 또한, 기존에는 gulp로 개발되어 있던 내용을 webpack으로 변경시키고자 했기 때문에, karma 테스팅도 webpack에 대한 내역을 가져오는 것이 좋겠다 생각하여 karma-webpack 플러그인도 같이 설치를 해주었습니다.

karma.conf.js 작성

karma.conf.js는 다음과 같이 변경했습니다 :)

const webpackConfig = require('./webpack.config');

// Karma configuration
// Generated on Mon May 08 2017 16:29:48 GMT+0900 (KST)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha', 'chai', 'phantomjs-shim'],

    // list of files / patterns to load in the browser
    files: [
      'test/**/*.spec.ts'
    ],

    // list of files to exclude
    exclude: [
      '**/*.swp'
    ],

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['verbose', 'spec'],

    failOnEmptyTestSuite: false,

    webpack: {
      devtool: 'eval-source-map',
      module: webpackConfig.module,
      resolve: webpackConfig.resolve
    },

    webpackMiddleware: {
      quiet: true,
      stats: {
        colors: true
      }
    },

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      'test/**/*.spec.ts' : ['webpack', 'sourcemap']
    },

    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],

    browserConsoleLogOptions : {
      level : 'log',
      format : '%b %T: %m',
      terminal : true
    },

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
}

webpack property를 보시면, 이전에 작성되었던 webpack.config.js 모듈을 require해서, ts에 대한 loader 및 resolve를 사용하고자 했습니다. files 속성에는 테스팅을 위해서 네이밍을 뒤에 .spec.ts 로 붙이기로 했구요, 이 부분을 테스트 suite로 설정하였습니다. framework에는 mocha, chai, phantomjs-shim 을 사용하고, reporters를 보시면 verbose를 추가하여 terminal에서도 상세 내역에 대한 log를 확인하고자 했습니다.

테스트할 파일을 만들어보기

저는 개발에 대한 폴더를 src로 설정하였고, 이참에 한 파일에 통으로 들어가 있던 파일을 모듈로 나눠보자 생각했습니다. :) gpx2czml에는 filereader 객체를 binarystring으로 받는 util이 존재하는데, 해당 util을 모듈로 분리하고 싶었습니다. utils라는 폴더를 하나 만들고, fileLoader.ts를 하나 작성했습니다. :)

//utils/fileLoader.ts
/**
 * File loader utils
 */
/**
 * file loader objects
 * @name fileLoader
 */
const fileLoader = {
  /**
   * initialize
   */
  init(): boolean {
    if (!FileReader.prototype.readAsBinaryString) {
      this.bindBinary();
      return true;
    } else {
      return false;
    }
  },
  /**
   * bind binary function
   */
  bindBinary(): void {
    FileReader.prototype.readAsBinaryString = function(fileData: any) {
      let binary = "";
      const pt = this;
      const reader = new FileReader();
      // file reader onload event
      reader.onload = (e: object): void => {
        var bytes = new Uint8Array(reader.result);
        var length = bytes.byteLength;
        for (var i = 0; i < length; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
          //pt.result  - readonly so assign binary
        pt.content = binary;
        const event = new Event('onload');
        pt.dispatchEvent(event);
      }
      reader.readAsArrayBuffer(fileData);
    };   
  }
};

export = fileLoader;

큰건 없습니다. 그냥 이전에 있던 코드를 객체로 module화 하고, typescript에 맞게 참조변수 등에 type을 지정해준거 말고는 없어요.. (아직 typescript 초보인지라;;) 이제 만들어 봤으니, 해당 파일을 테스트해볼 수 있는 코드를 하나 만들어보고자 합니다.

테스트 코드 작성

테스트 코드는 karma.conf.js에 지정해 두었던 것처럼 test 폴더를 만들고, 모듈을 테스트하기 위해서 fileLoader.spec.ts를 작성했습니다.

// test/fileLoader.spec.ts
'use strict';

import fileLoader = require('../src/utils/fileLoader');
import should = require('should');

describe('file loader test', () => {
  it('file loader is object', () => {
    should(typeof fileLoader.init).be.equal('function');
  });
});

큰건 아닙니다;; 이전 코드에서 typescript로 작성하기 위해 ts확장자로 변경했구요, 해당 모듈의 type이 object인지를 테스트 하기 위해서 should 플러그인을 사용, describe에 it을 통해서 fileLoader의 init함수의 type이 function인지를 테스트하는 구문입니다... 자! 이제 작성했으니 테스트를... 해보고자 했으나.. 실패합니다. describe, it이 typescript가 해석하기에 해당 모듈에 대한 참조가 없기 때문에 에러가 발생합니다.

DefinitelyTyped 플러그인 설치

이전에는 typescript를 사용할때 typescript 정의를 위해서 typings를 사용해서 정의를 했다고 합니다. 최근에는, DefinitelyTyped된 플러그인을 설치함으로써 좀더 간결하게 typescript 정의 환경을 설정할 수 있게 되었다고 하더군요. 따라서 왠만한 유명한 모듈들은 DefinitelyTyped 플러그인을 설치함으로써 IDE등에서의 typescript 정의 환경을 설정할 수 있다고 합니다. 이 부분에서 한참 해멨네요... 어째뜬! typescript가 정의된 mocha 플러그인을 설치하기 위해서 다시 terminal에 command를 입력합니다.

npm install @types/mocha --save-dev

설치하고자 하는 플러그인 앞에 @types/를 붙여 typescript 정의 환경을 설정합니다.

실행하기

terminal에 다음과 같이 실행하면 됩니다 :)

karma start

커맨드를 실행하면 다음과 같이 결과창이 출력됩니다...!

karma test results (전 개인적으로 이게 뜰때 굉장히 감동했던 기억이..)

번외) gulp로 테스트 script 작성!

command로 치기는 귀찮은 나머지.. gulp로 task 설정을 해보려고 합니다. (package.json에 넣어도 될텐데..)

    1. gulp 설치

      npm install gulp --save-dev
    1. gulpfile.js 작성

      // gulpfile.js
      var gulp = require('gulp');
      /**
  • test files
  • @name test */ gulp.task('test', function (done) { new karmaServer({ configFile : __dirname + '/karma.conf.js', singleRun : true }, done).start(); });

    1. terminal command 입력

      gulp test

결론

갈길이 멉니다...!! ㅠㅠ 아직 테스트환경밖에 못했으니.. 인제부터 typescript를 배워가며 만드는 일만 남았습니다. 많은 고수분들이 계시겠지만, 저같은 초보가 typescript를 적용하기 위함이니.. 혹시 다른 사항이 있거나 제가 놓친 부분이 있으면 충고 부탁드립니다 ㅠㅠ 감사합니다. :)

...