"생각의 웹"입니다.


Server side JavaScript platform인 Node.JS에서 사용할 유닛 테스트 프레임워크를 찾던 중 xUnit 계열인  nodeunit이 있어 이렇게 소개드리려고 합니다.

1. 설치

nodeunit은 https://github.com/caolan/nodeunit 에서 다운로드 받아 컴파일하거나 NPM을 통해 다운로드 받을 수 있습니다. 이때 node와 별개의 프로세스로 동작하기 때문에 -g 옵션을 주고 설치해야 합니다.

npm install nodeunit -g

설치가 완료되면 console 상에서 nodeunit 명령을 실행할 수 있습니다. 다음과 같이 수행하면 nodeunit의 사용법을 출력합니다.

nodeunit --help

2. 테스트 케이스란?


유닛 테스트 케이스(unit test case)는 테스트 대상 API (API under test), 테스트 조건(pre-condition and post-condition), 테스트 입력 값 (test input) 그리고 예상 출력 값 (expected output)으로 구성됩니다. 테스트 결과 판별 (assertion)은 보통 입력 값과 예상 출력 값이 같은 지를 비교하여 이뤄지며 그 결과를 취합하여 출력하게 됩니다.

3. 테스트 케이스 작성


다음은 가장 간단한 형태의 테스트 케이스 작성법입니다.


exports.testSomething = function(test){
    test.expect(1);
    test.ok(true, "this assertion should pass");
    test.done();
};

exports.testSomethingElse = function(test){
    test.ok(false, "this assertion should fail");
    test.done();
};


상기 예제를 보면 두 개의 테스트 케이스 (testSomething, testSomethingElse)가 존재하며, 결과 판별을 위해 test.ok()라는 API를 제공하고 있습니다.

이 API의 상세는 다음과 같습니다. 

interface Test {
   /**
    * Test if is a true value
    *
    */
    void ok(boolean value, optional DOMString message);
};


또한, 유심히 볼 필요가 있는 부분은 test.expect(1); 와 test.done(); 인데 이 API들은 JavaScript 특유의 비동기 동작(asynchronous operation)으로 인해 의도치 않은 결과가 나오는 것을 막기 위해 추가되었습니다.

좀 더 상세히 설명드리면, JavaScript는 콜백 함수(callback function)라는 형태로 요청한 동작의 결과를 되돌려 받는 경우가 많은데 이때 이 콜백 함수는 비동기적으로 호출되기 때문에 테스트 케이스를 잘못 작성하는 경우에는 호출되기 전에 테스트가 종료되는 경우가 종종 발생합니다.

이런 실수를 방지하기 위해서 nodeunit에서는 테스트가 끝나는 시점을 알려주는 test.done() API를 명시적으로 호출하도록 설계되었습니다.

또한, 테스트 케이스가 종료되기 전에 수행되어야 할 판별 (assertion)의 수를 test.expect(number) API로 호출하도록 해서 의도치 않는 결과 (false-positive)가 나오지 않도록 했습니다.

4. 보다 복잡한 테스트 케이스 작성


DB API와 같이 시간이 오래 걸리고 테스트 조건을 설정하는 데 많은 비용이 걸리는 경우를 위해 테스트 스윗(test suite)이라는 테스트 묶음을 위한 구조가 존재합니다.

테스트 스윗의 경우, 각 테스트 마다 선행 조건과 후행 조건이 실행될 수 있도록 setUp, tearDown 이라는 API를 제공합니다.

module.exports = {
    setUp: function (callback) {
        this.mysql = require('mysql');
        this.connection = this.mysql.createConnection({
            host: 'localhost',
            user: 'root',
            password: 'password',
            database: 'db'
        });
        this.connection.connect();
        callback();
    },
    tearDown: function (callback) {
        // clean up code here
        this.connection.end();
        callback();
    },

    testSqlWrite : function (test) {

        test.expect(1);
        this.connection.query('insert into tempData(tempDate, tempCelsius) values(?, ?)', [new Date(), 10],
            function (err, rows, cols) {
                if (err) {
                    test.ok(false, err);
                } else {
                    test.ok(true, rows);
                }
                test.done();
            });
    },

    testMysqlRead : function (test) {   
        test.expect(1);
        this.connection.query('select * from tempData',
            function (err, rows, cols) {
                if (err) {
                    test.ok(false, err);
                } else {
                    test.ok(true, rows);
                }            
                test.done();
            });
    }
};


상기 예제 코드는 Node.JS에서 MySQL를 사용할 수 있도록 mysql 모듈을 이용해 테스트 케이스를 작성한 것입니다.

이 코드를 수행하면, 1) setUp -> testMysqlWrite -> tearDown 2) setUp -> testMysqlRead 순으로 호출되게 됩니다. 코드 중 비 동기로 결과를 반환하는 API가 많음을 유념하시기 바랍니다.


이상으로 Node.JS 상에서 유닛 테스트 케이스를 작성하는 간단한 사용법을 소개드렸습니다. 코드를 작성하면서 테스트를 위해 작성했던 코드 뭉치 (code snippet)를 이와 같이 테스트 케이스로 작성하면 이후 변경 시 품질 관리 등에 유용하게 활용할 수 있습니다.


이상입니다. 감사합니다.  

안녕하세요. "생각의 웹"입니다.


이번 포스팅부터는 제목과 같이 Web IDL로 JavaScript API를 설계하는 방법을 여러분들께 공유해 보고자 합니다. 


먼저, 여러분에게 JavaScript API를 설계해야 하는 당위성과 그리고 Web IDL이 무엇인지에 대해서 설명드려야 하겠죠.


우선 첫번째 JavaScript API를 설계해야 하는 이유부터 말씀드리겠습니다.

  • JavaScript는 스크립트 언어라는 특성 상 type 선언 없이 변수를 생성하고 유연한 형 변환(type casting)을 통해 컴퓨터 언어의 지식이 부족한 초급 개발자들도 쉽게 사용할 수 있을 뿐만 아니라 함수형 언어의 특성을 갖는 객체 지향 언어로서 확장성과 유연성이 좋아 고급 개발자에게도 유용한 언어입니다.

  • 웹을 지원하는 모든 형태의 기기에서 동작하는 클라이언트 앱 외에도 Google이 만든 V8 엔진을 이용해 만든 Node.JS라는 서버 프레임워크에서도 동작하는 서버 앱 그리고 Mongo DB라는 NoSQL DB에서도 사용 가능한 매우 범용적인 개발 언어입니다.

  • 웹에서 동작하는 앱은 대부분 브라우저의 개발자 모드 (F12 키)를 통해 JavaScript code를 살펴 볼 수 있고 이런 수고가 아니라도 구글링을 통해 다양한 라이브러리 혹은 코드 조각 (code snippet)를 검색할 수 있습니다. 원하는 기능의 대부분을 단순히 복사 & 붙여 넣기로도 구현할 수 있습니다. 

  • 이렇게 코드를 훔쳐 사용하기 쉬운 구조 때문에 어차피 훔쳐 사용할 거라면 이걸 하기 위해 분석하는 수고를 덜어주는 마음씨 착한 개발자의 도움으로 인해 재사용하기 쉬운 형태로 만든 라이브러리가 매우 많이 있습니다. 물론 대부분 공짜구요. 이때 좋은 라이브러리는 API만 알아도 기능을 사용할 수 있도록 사용자에게 제공합니다. 코드를 모두 읽어 봐야 한다면 '복사 & 붙여넣기'보다 나은게 없으니까요.

  • API는 Application Programming Interface의 약자로 말 그대로 앱을 프로그래밍하는 인터페이스, 즉 앱에서 수행될 기능을 짜는 방법이라고 볼 수 있습니다. JavaScript 앱을 작성할 때 API의 도움을 받으면 적은 노력으로 원하는 기능을 구현할 수 있습니다.

  • API에 이용해 앱을 짜는데 자신감이 붙었다면 (게다가 혹시 개발 비 명목으로 돈도 벌었다면) 라이브러리가 제공하지는 않지만 앱을 짜는데 필요했던 기능을 API로 설계해서 추가해보면 어떨까요? 이런 너그러운 마음씨가 당신이 했던 수고를 반복하지 않고 당신이 알지 못하던 새로운 기능을 개발할 수 있도록 도울 겁니다. 당신이 사용했던 라이브러리를 개발한 원 저자가 그랬듯이 말입니다.

  • 좋은 앱은 많은 사람들에게 유용한 기능을 제공해 주지만 모든 사람들을 만족시켜 줄 수 없습니다. 사람들의 취향이란 사람들의 숫자 만큼이나 다양하니까요. 그들에게 DIY (Do It Yourself) 할 수 있도록 해 준다면 메일 함에 쌓이는 다양한 수정 요구사항에서 조금은 해방될 수도 있습니다. (그렇다고 버그에서 해방되는 걸 의미하지는 않습니다.)

  •  미래는 API의 시대가 될 것이라고 예견하는 사람들이 있습니다. (당연히 저도 그런 사람 중 하나입니다.) 소프트웨어 교육이 보편화 되고 있기에 대부분의 사람들이 프로그래밍을 할 수 있게 되리라고 보기 때문이죠. 따라서, 머지않아 단순히 API를 활용해 앱을 짜는 것은 더 이상 신기한 일이 되지 않겠지만, 새로운 기능을 제공하는 API를 만들어서 제공하는 역할은 여전히 전문가의 영역에 남아 있을 것입니다.

쓰다 보니 길어져서 한줄 요약하면 다음과 같습니다.

JavaScript는 시장이 크고 유용성이 높은 개발 언어로 API를 설계할 줄 알면 전문가로 대접 받을 수 있다. - 웹 오브 띵크

 

동기 부여가 되는 이야기를 한건지 모르겠지만 혹여 여기까지 읽으셨다면 필자는 여러분들이 API를 설계하기로 충분히 세뇌(?) 되었다고 생각하고 두 번째인 Web IDL에 대해 설명드리겠습니다.


일단 Web IDL 에 관련된 문서가 있는 아래 링크를 한번 방문해 보시죠. 


http://www.w3.org/TR/WebIDL/


영문으로 된 문서는 무조건 번역기를 돌리다 보니 무슨 소린 줄 모르시겠다는 분들과 영어에 자신있으나 배경 지식이 없어 이해가 안가시는 분들을 위해 요약 (abstract)을 한글로 번역해 보았습니다.


이 문서는 Web IDL 이라는 인터페이스 정의 언어를 정의하는데 웹 브라우저에서 구현될 것을 의도한 인터페이스들을 설명하는데 사용될 수 있다. Web IDL은 웹 플랫폼에서 사용되는 공용 스크립트 오브젝트들의 동작을 보다 읽기 쉽도록 명세화하기 위한 수많은 기능들을 가진 IDL의 변종이다. Web IDL로 명시된 인터페이스들이 어떻게 ECMAScript 실행 환경 내에서 구성되는 지에 대해서도 상세화 되어 있다. 이 문서는 이미 배포된 스펙 문서를 어떻게 구현할지에 대한 가이드을 개발자에게 제공하고 새로 배포하는 스펙 문서의 인터페이스의 구현체가 서로 호환되도록 보장하기 위해 참조하기 위함이다. - W3C Web IDL Abstract


등장한 용어들에 대해 간단히 설명 드리면 다음과 같습니다. 또 의아한 용어가 있다면 댓글로 남겨주시기 바랍니다. :-)

  • "정의" - Justice가 아닌 Definition 입니다. 전 공대 출신이니까요. ;-)
  • "웹 브라우저", "웹 플랫폼" - 모두 여러분이 웹 세계를 탐험하는 도구(앱)를 의미하나 브라우저는 사용자 관점에서 플랫폼은 개발자 관점에서 바라보는 겁니다.
  • "오브젝트" - 한글로는 객체라고 번역되나 프로그램에서 기능을 수행하는 단위라고 이해하면 됩니다.
  • "ECMAScript" - 여기서는 JavaScript와 동의어라고 이해하면 됩니다.
  • "스펙" - 대학이나 취업 시 적어내는 이력서가 아니라 정의한 내용을 적은 규격서입니다. 
  • "구현체" - 코딩을 완료해서 동작하는 프로그램을 의미합니다. 


발췌한 요약문에서 빨간 색 밑줄친 부분은 주의 깊게 봐주셨으면 합니다. 제가 Web IDL로 JavaScript API를 설계하는 데 사용하는 이유를 말해주는 대목이니까요. 이 내용에 대해 이후 포스팅에서 좀 더 자세하게 설명드리겠지만 먼저 간략히 말씀드리면 JavaScript 언어의 유연성에 대한 부작용으로 인해 API를 구체적으로 명세하기 어려운 점이 발생합니다. 이렇게 API의 동작을 명확하게 알려주지 못한다면 사용하는 사람 뿐 만 아니라 API를 구현하는 사람에게도 혼란을 초래하기 때문에 구체적인 명세화 방식이 꼭 필요합니다.


게다가 이외에도 Web IDL를 사용하면 추가 이득을 얻을 수 있는데 그것이 바로 API 설계 검증 및 문서화에 대한 자동화입니다. 아래 링크의 widlproc이라는 도구를 통해 설계자는 설계의 유효성을 검증하고 손쉽게 문서를 생성할 수 있습니다. 이 방법 역시 추후 포스팅으로 설명드리겠습니다.


widlproc: https://github.com/dontcallmedom/widlproc  

 


이번 포스팅은 여기까지 입니다.


감사합니다.


안녕하세요. '생각의 웹'입니다.


한국의 테크 샵인 대디스랩 지원에 힘입어 빠르게 프로토타이핑한 '홈 센서 프레임워크'을 소개합니다.

'홈 센서 프로임워크'는 스마트 홈 환경에서 사용자에게 필요한 서비스를 발굴하기 위해 데이터를 모으고 데이터를 분석해 컨텍스트를 발굴하기 위한 JavaScript 개발 환경입니다. 


 상세한 내용은 아래 슬라이드를 참고하시기 바랍니다.



덧붙여 제가 생각하는 이 프레임워크가 가지는 장점은 다음과 같습니다.

    • 오픈 소스 하드웨어를 이용해 스마트 홈 관련 아이디어를 손쉽게 DIY 
    • 웹 월드의 일등 시민인 JavaScript 만으로 서비스 개발 가능
    • Open API (RESTful Web API)와 연동한 서비스 개발 가능
    • 사생활 침해의 우려가 있는 민감한 컨텍스트 정보를 클라우드가 아닌 댁 내에 저장
    • HTML5 기반 멀티 스크린 (N-Screen) 서비스 ready   

개발 관련해서 궁금한 점이나 아이디어 있으시면 댓글로 남겨주세요.


감사합니다.


덧글1. 

라즈베리 파이에서 MySQL 설치가 제대로 되지 않을 경우, 아래 링크를 참고하시기 바랍니다.

http://likeplex.com/Blog/Archives/92


덧글2. 

'밸브의 신' 덕분에 의도치 않게 이 슬라이드가 관심을 많이 받게 되었네요.

슬라이드를 보고 진행하시다가 막히는 부분을 댓글로 연락처와 함께 남겨주시면 A/S 해드리도록 하겠습니다. 







+ Recent posts