Outsider's Dev Story

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

Blanket.js : 자바스크립트 코드 커버리지 라이브러리

코드 커버리지

코드 커버리지라 하면 소스코드에 대한 테스트코드를 작성했을 때 테스트코드가 소스코드를 어느 정도 커버하는지 퍼센티지로 나타낸 것을 말한다. 테스트를 수행해서 소스코드를 전부 테스트하면(정확히는 실행하면) 100% 커버리지가 되고 소스라인 중 일부가 빠지면 50%, 70% 등으로 나타낸다. 코드 커버리지에 대해서는 이견이 많은데 일반적으로 보면 이견은 코드 커버리지 수치를 어떤 강제사항으로 둠으로써 불필요한 코드에 대한 테스트코드를 의미없이 작성하게 되기 때문에 발생하게 된다. 그러니까 테스트 코드를 작성하는 의미가 그다지 없는 부분에 대한 테스트를 작성함으로써 고의로 수치를 올리는 어뷰징이 발생할 가능성이 높기 때문이다.

하지만 이런 부작용을 제외하고 코드를 작성할 때 테스트코드를 작성하는 것이 중요하기 때문에 강제의 용도가 아닌 테스트해야 하는데 누락된 부분을 확인한다는 면에서 커버리지를 확인하는 것은 의미가 있다. 사실 테스트가 잘된 코드는 커버리지가 높지만 그 역은 성립하지 않는다. 이는 커버리지가 소스코드의 라인(주석이나 공백 제외하고)이 실행되었는지로 검사하는데 실제 테스트를 작성하면 같은 부분에 대해서 다양한 값(경계값이나 정상값등)으로 테스트를 하게 되므로 같은 부분을 철저히 검사한다고 커버리지가 특히 올라가게 되지는 않는다.

브라우저 자바스크립트 코드 커버리지

최근에 브라우저(Node.js가 아니라)에서 자바스크립트의 코드 커버리지를 측정할 일이 있었다. 자바스크립트용 커버리지 도구는 JSCoverage, JSCover, istanbul등 몇가지가 존재하는데 내 용도에 잘 맞지 않았다. 내가 하고 싶었던 것은 테스트를 실행해서 커버리지를 취합한 다음에 이를 JUnit형식의 XML이나 TAP으로 CI에서 리포팅을 하고 싶었는데 잘 되지 않았다. 좀 더 정확히 말하자면 브라우저 테스트같은 경우 서버측 언어와는 달리 브라우저에서 HTML을 실행하는 방식이고 요즘 같은 경우는 Phantom.js를 이용해서 자동화하는게 일반적인데 이 때문에 Runner같은 걸로 전체 테스트를 한번에 돌리지 않고 개별적으로 돌아서 파일별로 커버리지는 나오지만 취합해서 하나로 리포팅하기가 무척 어려웠다.

나는 Mocha를 주로 쓰고 있고 mocha의 HTML 커버리지 리포트가 이뻐서 써보려고 했지만 브라우저의 코드 커버리지 측정 지원은 아직 이슈가 열린 채로 있는 상태다. 좀 더 정확히는 Phantom.js와 조합해서 측정은 되는듯 한데 리포트하는데 좀 이슈가 있다. JSCover는 자바로 만들어졌는데 난 Grunt를 써서 이건 안써봤다. istanbul은 Grunt와 연동하는데 좀 이슈가 있었다. 결국 테스트 커버리지를 측정해서 리포팅하는 작업을 한참동안 하다가 지칠만큼 지쳤다.

Blanket.js

Blanket.js는 이번에 작업을 하다가 새로 알게된 라이브러리이다. 먼저 말하자면 앞에서 얘기한 CI에 리포팅하는건 포기했고 커버리지를 개발자가 확인할 수 있는 Blanket.js로 타협을 본 상태이다.

Blanket.js 홈페이지

웹사이트에 나온 Seamless javascript code coverage라는 문구는 정말 사실이다. 진짜 쉽다. 대부분의 JS 커버리지 도구는 JS 특성상 코드의 실행여부를 확인하기 위해서 소스코드를 커버리지를 측정할 수 있는 코드가 삽입된 코드로 변환한다.(이를 이쪽에선 instrumented라고 부르는 듯) 즉 js라는 폴더에 소스코드가 있으면 js-cov라는 폴더를 만들러서 커버리지용 소스코드를 만들고 테스트코드에서는 이 폴더를 바라보게 해서 테스트를 수행하고 커버리지를 측정하는게 일반적이다. Node.js에 비해서 브라우저에서는 이 대상을 바꾸는 것도 귀찮은 일이지만 Grunt를 이용하면 이도 어렵사리 할 수 있긴 하다. 하지만 Blanket.js는 그냥 라이브러리를 불러만와도 커버리지를 측정할 수 있다.

QUnit으로 테스트 하는 경우를 보자.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>QUnit Example</title>
  <link rel="stylesheet" href="../bower_components/qunit/qunit/qunit.css">
</head>
<body>


</body> </html>

위와 같이 일반적인 Qunit 테스트코드에서 Qunit용 blanket.js 파일만 불러온 다음 커버리지를 측정할 스크립트 태그에 data-cover라는 어트리뷰트만 추가해 주면 된다.(기본적으로는 Qunit과 Jasmine을 지원한다.) 이제 브라우저에서 Qunit 테스트를 실행하면 다음과 같이 나온다. Qunit에서는 기본적으론 코드 커버리지가 안나오고 상단에 Enable coverage를 체크하면 하단에 커버리지가 나타난다.

QUnit 테스트 실행시 커버리지가 함께 나온 화면

테스트가 수행된 라인과 커버리지가 파일별로 리포팅되고 해당 파일을 클릭하면 다음과 같이 어느 부분이 누락되었는지 빨간색으로 표시가 된다.

Blanket 커버리지에 커버리지에 누락된 코드가 표시된 화면

이번엔 mocha로 테스트 커버리지를 확인하는 경우를 보자.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Mocha Tests</title>
  <link rel="stylesheet" href="../bower_components/mocha/mocha.css" />
</head>
<body>


</body> </html>

mocha에서 blanket.js를 사용할 때는 mocha용 어댑터파일도 함께 불어와야 한다.(yui용 어댑터도 있다.)

Mocha 테스트에서 Blanket 커버리지가 표시된 화면

이제 mocha 테스트를 돌리면 Qunit과 동일하게 하단에 코드 커버리지가 나타나는 것을 볼 수 있다.

클라이언트 자바스크립트의 경우 HTML 파일별로 테스트를 실행하기 때문에 하나의 자바스크립트 파일을 여러 HTML 테스트 파일로 나누어서 하는 경우에는 커버리지가 따로 측정되므로 blanket.js를 사용하는 경우 이러한 부분에 대한 고려도 해야 한다.

2013/08/07 01:19 2013/08/07 01:19