JUnit in Action 책 출간 기념으로 짤막한 글 하나 번역해본다.
원문: JUnit 4 in 60 Seconds
이번 주말에 JUnit 4 라이브러리를 살펴보고 간단히 정리해보았다.
테스트 케이스임을 명시하기 위해 사용한다. “test”와 같은 접두어를 붙일 필요가 없어졌다. 또한 테스트 클래스 역시 더 이상 “TestCase” 클래스를 확장할 필요가 없어졌다.
@Before와 @After 애너테이션을 사용하여 “setup”과 “testDown” 메서드 명시한다. 이 메서드들은 각각의 테스트 전후로 실행된다.
@BeforeClass와 @AfterClass는 클래스 단위의 “setup”과 “teadDown” 메서드에 붙인다. 1회성 setup, tearDown 메서드라 생각하자. 클래스고 파홈한 모든 테스트케이스들의 전후로 단 1회만 실행된다.
예외 발생이 예상되는 테스트 케이스에는 @Test 애너테이션에 “expected” 파라미터를 사용한다. 발생해야할 예외의 클래스 명을 적어두면 된다.
무시하고자 하는 테스트 케이스에는 @Ignore 애너테이션을 붙인다. 무시하는 이유도 기입해 넣어주면 좋다.
제한 시간이 필요하면 “timeout” 파라미터를 이용한다. 단위는 밀리초이다. 테스트가 제한시간 내에 완료되지 못하면 실패 처리된다.
배열 비교에 쓰일 수 있는 새 단언 메서드들이 추가되었다. 배열의 길이가 같고, 각 원소들이 대상 배열의 대응되는 원소들과 같아야(equal) 한다.
JUnit 3에서 JUnit 4용 테스트를 실행하려면 JUnit4Adapter를 사용한다.
자! 그럼 모두 즐코딩~ ^^
드디어 판매 개시!!!!
처음 작품인데, 반응이 어찌 나올지 궁금.
다음 기회에는 저술을 하거나, 번역을 하더라도 나의 이야기를 좀 더 많이 실을 수 있길 바래본다.
Edge of Chaos | Agile Development Blog 에 Kanban 의 Cumulative Flow Chart 활용 예[1]가 실려서 옮겨본다.
(Kanban 에 대한 배경 지식이 전혀 없다면 One day in Kanban land [2] 를 먼저 읽어보고 오자. 흥미가 생긴다면 Lean and Kanban[3]의 글들을 시간을 두고 찬찬히 읽어보길 권한다.)
차트를 보면 우리가 12월 초에 병목을 겪었음을 볼 수 있다. 꾀 복잡한 유저 스토리 하나가 원인이었다. 이론적으론 유저 스토리 하나가 개발 주기에 심각한 영향을 미치거나 병목을 발생시키면 안되지만, 규칙을 조금 어기면 실제 그런 일이 일어날 수도 있다.
문제의 유저 스토리는 jQuery 자바스크립트 프레임워크를 ExtJS 프레임워크[6] 로 교체하는 것이었다. 이 작업은 개발자 한 명이 별도의 브랜치에서 1개월에 걸쳐 구현하였다. 그 한 달 동안 나머지 멤버들은 몇 차례의 릴리스를 성공적으로 마쳤다. 테스터들은 그 유저 스토리에서 별 문제점을 발견하지 못했고, 인수 테스트(acceptance test) 역시 모두 통과하였다. 이 코드를 메인 코드 브랜치에 반영하는 것은 당연한 수순이었고, 그렇게 했다.
불행히도, 코드 반영 후 스모크 테스트 중 꾀 많은 빌드 에러들이 발생하였다. 버그를 다 잡는데는 1주일 이상이 소요되었고, 그 동안 우리는 아무것도 릴리스하지 못했다. 이미 반영된 코드를 다시 롤백하는 것 역시 만만치 않았기 때문에 뾰족한 수가 없었다.
여기서 얻은 교훈은 근본적으로 보다 복잡한 유저 스토리에는 테스트에 더 많은 노력을 들이라는 것이다. 이런류의 스토리는 어플리케이션에 다방면에 걸쳐 영항을 미치고, 보통의 스모크 테스트만으론 충분치 않다. 그래서 우리는 병합 전에 더 세심한 테스팅과 검증이 필요함을 의미하는 새로운 부류의 서비스를 제공할 것이다. 일단 “기술적으로 복잡한 스토리”라고 불러보자.
일반적으로, Cumulative Flow 차트는 과거 데이터를 분석하는데 훌륭한 툴이긴 하지만, 긴급한 병목을 식별해 내는데는 Kanban Board 가 훨씬 효과적이다. Kanban Board 에서 최대 허용 작업 수(limit)에 도달함은 곧 무엇가 문제가 있음을 뜻한다.
STEN [1] 에서 재미난 설문을 하고 있다. 아직 진행중이지만 상황을 대략 파악할 정도는 나온 듯 싶다.
“국내 프로젝트에서 애자일을 도입했다가 실패했다면 그 이유는 무엇인가?” 1. 국내의 전반적인 소프트웨어 개발 프로세스 성숙도가 낮기 때문 (19.0%) 2. 과도한 애자일 프랙티스를 경험이 부족한 상태에서 여러가지를 동시에 적용하려 하기 때문 (25.4%) 3. 애자일한 개바 프로젝트에서 테스팅을 어떻게 해야할지 잘 모르기 때문 (9.5%) 4. 애자일 개발의 사상이나 이의 도입에 따른 개발 문화의 변화에 대한 고려없이 테크닉만으로 접근하기 때문 (44.4%) 5. 기타 (1.6%)
“국내 프로젝트에서 애자일을 도입했다가 실패했다면 그 이유는 무엇인가?”
1. 국내의 전반적인 소프트웨어 개발 프로세스 성숙도가 낮기 때문 (19.0%) 2. 과도한 애자일 프랙티스를 경험이 부족한 상태에서 여러가지를 동시에 적용하려 하기 때문 (25.4%) 3. 애자일한 개바 프로젝트에서 테스팅을 어떻게 해야할지 잘 모르기 때문 (9.5%) 4. 애자일 개발의 사상이나 이의 도입에 따른 개발 문화의 변화에 대한 고려없이 테크닉만으로 접근하기 때문 (44.4%) 5. 기타 (1.6%)
나는 4번을 찍었다. 물론 다른 이유들도 많다. 예를 들어 팀원 & 조직 전체가 변화의 필요성에 대해 공감한 상태에서 진행하느냐도 포함될 수 있다. 그리고 어느 하나의 이유보다는 여러 가지가 복합적이다.
나도 애자일 도입을 외치지만, 수많은 경험을 통해 아주 신중하게 접근해야 함은 뼈저리게 느끼고 있다. 어설프게 접근했다가는 ‘해봤는데.. 별 효과 없더라.’라는 부정적 인식만 남기기 쉽기 때문이다. 그리고 이는 소위 heavyweight 개발 프로세스 등 SE 가 지금껏 저질러왔던 과오이다. 애자일에서도 똑같은 일이 반복된다면 개발 문화를 개선할 수 있는 기회가 언제 다시 올 지 예측하기 어렵다.
한 4년쯤 전에 정리를 시작했던 주제로, 지인 몇 명과 논문으로 써볼까 기고를 할까 고민하다 제 때 빛을 보지 못했다. 실례를 찾아 보강하는 것이 가장 큰 숙제였는데, 불행히도 그 후 테스트 관련 업무를 접할 기회가 없었어서 기고까지는 하지 못했다.
In other to make software testable, designer should follow some rules. If you are interested in software design, some of them must be familiar to you. That’s because they are rules for improving software ‘design‘ in testability perspective. Lets look into the rules one by one.
Software which satisfies these rules can be called testable. However, it is very hard to measure quantitatively how well the rules are reflected. I’ll remain this issue for other dedicated articles.
(in Korean)
테스트 가능한 소프트웨어를 만들기 위해서는, 설계자는 몇 가지 규칙을 따라야 한다. 소프트웨어 설계에 관심있는 사람이라면, 친숙한 이름의 규칙들을 찾을 수 있을 것이다. 이유인 즉, 이 규칙들은 테스트의 관점에서 소프트웨어의 ‘설계‘를 향상시키기 위한 지침이기 때문이다. 그럼 그 규칙들을 하나씩 살펴보도록 하자.
이상의 규칙들이 충족된 소프트웨어라면 ‘테스트할 수 있다’고 얘기할 수 있을 것이다. 단, 이런 규칙들이 얼마나 잘 반영되었는지를 정량적으로 측정하는데는 분명한 한계가 있다. 측정 이슈는 주제의 범위를 벗어나므로 본 글에서는 더 자세히 다루지 않을 것이다.
(Read the full article)
디버깅을 잘 한다.
나는 과거 종종 그런 얘기를 들은 적도 있고, 또 스스로도 제법 잘 한다고 생각한다. (최근 몇 년간은 직접적인 개발과는 거리가 좀 있는 업무들을 주로 수행해 왔다.)
그런데 ‘디버깅을 잘한다’는 말에는 어떤 의미가 포함되어 있을까.
아무 개념 없이 엉터리로 짠 남의 코드에서 산발적으로 발생하는 미지의 문제를 소스 코드만 추적해서 잘아낼 수 있으면 디버깅을 잘 하는 것일까? 분명 이런 능력은 대단한 것겠지만.. 현실적으로는 ‘운이 좋았다’ 이상을 기대하긴 어렵다. 주변에서도 능력 있는 개발자가 다른 프로젝트 합류 후 ‘내가 할 수 있는 일이 없다’고 푸념하고 경우를 몇 번 보았다. 이유는 몇 년 동안 들여다보던 사람이 아니면 도저히 손 댈 엄두가 안나는 코드를 사용하고 있기 때문이었다. 종속된 모듈과 프로젝트가 많고 덩치도 만만치 않아 새로 깔끔히 만들 수도 없다는 것이다. 동작하는 코드를 새로 만들 시간을 달라는 요청은 관리자들에게 쉽게 묵살당한다.
결국 아무리 능력 좋은 개발자도 대상 소프트웨어의 상태/환경에 따라 발휘되는 능력은 극심한 편차를 보이기 마련이다. 좀 더 정리하여 이야기하면, 커버할 수 있는 임계점 이하까지는 쉽게쉽게 문제를 찾아내지만, 그 한계를 넘어서면 거의 컨트롤이 불가하여 평범한 개발자와 별 차이를 보이지 못하게 된다. 이는 인간이 머릿속에 한 번에 담고 분석/추적할 수 있는 정보량이 그리 많지 않기 때문이다.
중요한 것은 디버깅 대상을 단순 명료하게 유지하는 능력이다. 또는 복잡한 대상을 단순하게 변형하는 능력이다. 구체적인 방법들을 떠올려보자.
이상은 순수한 소스 코드 & 설계의 관점에서의 디버깅 능력 향상 방법들이었다. 유지보수를 위한 지침과 동일하다고 볼 수 있다. 그럼 다른 관점에서는 또 어떤 방법들이 있을까?
이상은 소스 코드 외적인 방법이었지만, 개인이 충분히 할 수 있는 것들이다. 그럼 마지막으로 소셜 개발자라면 또 어떠한 방법들을 생각해볼 수 있을지 나열해보겠다.
디버깅 하나 얘기하면서 참 많은 것을 훑었다. 오버라고 생각할 수도 있겠지만, 개발이라는 것이 그리 딱딱 떨어지는 것이 아니고.. 이것이 현실이다. 오히려 위에 나열할 것 외에도 수많은 요소들이 훌륭한 디버거를 만드는 관여될 것이 분명하다.
자!! 그럼 지금까지 나온 좋은 디버거로서의 자질은 정리해보자.
Noop. 구글 주도로 만들어지고 있는 새로운 언어로, ‘노옵’ 이라고 발음한다. (Click Here)
아직은 컨셉을 정리하고 있는 상당히 초기 단계지만, 목표로하는 바는 제법 흥미롭다. 바로 테스터빌러티를 언어 차원에서 지원하겠다는 것이다. 타이틀에도 ‘A testable programming language running on the JVM’ 이라고 적혀 있을 정도다. 그 외 특징은 다음과 같다.
테스트는 굉장히 중요한 요소이지만, 언어와는 독립적으로 떨어져 있기 때문에, 프로그래밍 언어를 배우면서 테스트까지 배우지는 않는다. 요즘은 언어별 유명한 테스팅 툴/프레임워크가 하나씩은 다 있지만, 아무래도 별도 배움을 요하는 것은 어쩔 수 없는 현실이다. 그 때문에 많은 개발자들은 개발자로서 갖춰야할 기본 소양 중 중요한 것 하나를 제대로 쌓지 못하고 있었던 것 또한 사실이다.
이 언어가 어떻게 발전해서 어떤 영향을 미칠 지는 아직 예측하기 어렵다. 혹 언어 스펙에 관심있는 사람이라면 이 그룹에 참여해 쓸만한 커맨트를 남겨놓기 바란다. 혹시 아는가? 내가 남긴 말 한 마디가 훗날 한 시대를 풍미할 언어의 중요한 속성 하나에 영향을 주게 될지..
내가 지금까지 접해본 여러 이론/실천법 들을 통틀어 가장 맘에 드는 것들을 세 가지 고르라면 TDD, Refactoring, Scrum, 이렇게 세 가지를 뽑겠다. (우리 조직에선 이 중 단 하나도 하지 않고 있어서 참으로 답답하고 안타깝다.) 다른 사람들과는 좀 다른 관점일 수 있겠는데, 이들에 애착이 생기는 내 나름의 이유는 간략히 정리해본다.
TDD (Test Driven Development) – 보통 언급은 되지만 크게 부각되지 않는 장점. 종종 설명에서 아예 빠지기도 한지만, 내가 가장 높게 쳐주는 TDD의 장점은 바로 ‘개발자들의 설계 능력의 향상’이다. 테스트는 곧 사용자의 사용 패턴을 시뮬레이션 한 것으로, 쉽게 테스트하기 위한 고민은 바로 쉽게 사용하기 위한 인터페이스를 고민하는 것이다. 이 과정을 몇 개월만 반복하더라도 테스트하기 쉬운 설계(testable design)와 그 반대의 케이스의 대표적인 사례(testable design anti-patterns)들을 한 다발 발견해낼 수 있을 것이다. 디자인 공부한답시고 UML 다이어그램 책이나 디자인 패턴 책을 열심히 파는 것보다, 자신이 개발중인 코드를 보고 테스트를 어떻게 할까를 고민해보는 것이 훨씬 효과만점이라고 자신있게 주장할 수 있다.
업계에선 이 부분이 잘 수행되지 않고 있는데, ‘테스트 == 설계’ 라는 관계가 잘 부각되지 않기 때문으로 보인다. (아쉽게도 팀원의 역량 향상을 등한시하는 매니저도 제법 있다.) 설계는 중요시하면서도 테스트는 등한시 하는 것이다. 개발자에게 설계를 잘 하라면서도 테스트는 외부 인력에 의존하는 경우가 너무 많다. 테스터들도 자신이 설계를 검증해야 한다는 것을 자각하지 못하고 있고, 혹 있다손 치더라도 설계에 대해 이러쿵 저러쿵 하는 것을 개발팀에서 그리 달가워하지 않는 경우도 종종 있다. 그리고 테스트를 너무 늦게 시작해 설계 문제가 드러나도 일정상 수정하지 못하는 안타까운 상황도 흔히 발생한다.
기본적인 테스트(유닛, 인티그레이션)는 가능한 모두 개발자들 스스로 수행하도록 하고, 외부 인력은 신뢰성, 고가용성, 보안, 스레드 안정성 등 전문 분야에 대해서 검증을 수행해 주는 것이 효율적이다. 개발자 테스트 단계에서도 단순 기능 검증이 아닌 테스트 용이성에 큰 비중을 주도록 꼭! 주지시켜야 한다.
이렇게 훈련된 개발자들은 나중에 혹 테스트 케이스를 작성할 시간이 부족하더라도 처음부터 상대적으로 수준 높은 설계를 만들어낸다. 신입사원들에게 별 쓸모 없는 프로세스나 테크닉 교육은 대폭 줄이고 TDD 나 한 두 달 시켜주면 현업에 훨씬 도움이 될 것이다. 대학과 확원에서도 이론과 테크닉에만 치우지지 말고 이런 실질적인 교육과 훈련에 좀 더 투자를 해야 한다.
다시 한 번 강조하는 것은 ‘개발자‘의 역량 향상이다. 그 효과는 영구적이고 사기 증진에도 많은 도움이 된다. 제품의 설계 향상 같은 단기적인 이점은 그에 비해 훨씬 가치가 적다.
TDD 에 관심이 있는 사람이라면 BDD (Behavior Driven Development – Click Here) 도 한 번쯤 꼭 참고해보도록 하자. TDD 의 발전 형태로 볼 수 있는데, 무엇을 어떤 식으로 테스트해야할 지에 대한 좋은 가이드라인을 제시해준다. 개념을 확실히 인지하고 있다면 전용 툴 지원 없이 전통적인 Unit Test Framework 만으로도 BDD 를 활용할 수 있다.
단순 API 테스트라면 boundary value analysis (Click Here) 와 equivalence partitioning (Click Here) 정도는 확실히 알아두자. 이 둘을 조합하면 많은 경우에 있어 기계적으로 test case 들을 뽑아낼 수 있다. SE, SQA, 혹은 전문 테스터로서 역량을 원한다면 이곳 (Click Here) 도 좋은 레퍼런스가 될 것이다.