Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Vows에서 비동기테스트를 위한 this.callback의 관례

이전에 Vows에 대해서 포스팅한 것처럼 비동기테스트를 사용하기 위해서는 vow가 콜백에 응답할 수 있어야 하기 때문에 topic에서 this.callback을 사용하게 되고 해당 콜백이 실행될 때 각 vow의 함수들이 이 콜백을 받게 됩니다. 그래서 비동기테스트를 진행했는데 테스트 실패가 아닌 오류가 발생하면서 this.callback이 제대로 동작하지 않았습니다. 예를 들어 다음과 같습니다.


var vows = require('vows'),
      assert = require('assert');
 
var doSomething = function(callback) {
  callback(1);
}

vows.describe('this.callback test').addBatch({
  'when callback occered': {
    topic: function () {
      doSomething(this.callback);
    },
    'should be successed': function(param) {
      assert.equal(param, 1);
    }
  }
}).run();

테스트할 함수에 thsi.callback를 넘겨주고 콜백이 넘겨준 값을 테스트하는 간단한 spec입니다. 하지만 이렇게 작성을 하고 테스트를 실행하면 아래처럼 오류가 납니다.

vows 테스트시 오류가 발생한 화면

처음에는 로직이 오류가 있는 것으로 생각했는데 로직은 이상이 없는데도(위 예제처럼) vow가 콜백을 받으면서 An unexpected error was caught가 발생했습니다. 이 문제로 꽤 고생을 했는데 문제는 상당히 간단한곳에 있었습니다. node.js에서는 관례적으로 콜백을 사용시 첫번째 파라미터로 err를 받도록 하고 있습니다.

function callback(err, result) {}

node.js 내장함수들을 포함해서 이런 형태의 콜백을 쓰는 것이 관례이고 Vows도 이 관례를 따르고 있기 때문에 콜백의 첫번째 파라미터가 null이 아닌 어떤 객체가 넘어오게 되면 해당 테스트를 진행하는데 오류가 발생했다고 생각하고 오류를 뿌려주게 됩니다.


var doSomething = function(callback) {
  callback(null, 1);   // <- fixed here
  // or callback('', 1);
}

vows.describe('this.callback test').addBatch({
  'when callback occered': {
   topic: function () {
     doSomething(this.callback);
   },
   'should be successed': function(err, param) {   // <- fixed here
     assert.equal(param, 1);
   }
  }
}).run();

위와 같이 node.js의 콜백 관례를 따라주면 정상적으로 테스트가 진행이 됩니다.(이런건 문서에 명시적으로 표시를 해줬으면 하네요 ㅠㅠ) 관례는 따르는게 좋다고 생각하지만 관례를 따르지 않고 콜백을 사용해서 테스트하고 싶다면 run() 메서드에 다음과 같이 오류를 체크하지 않도록 파라미터를 주면 됩니다.

vows.describe('').addBatch({}).run({error: false});

테스트 러너를 위해서 Suite를 외부로 내보내는 경우는 아래처럼 옵션을 줄 수 있습니다.

vows.describe('').addBatch({}).export(module, {error: false});

2011/08/11 01:28 2011/08/11 01:28