달력

05

« 2012/05 »

  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
세계 최초의 법전을 알고 계시나요? 바로 함무라비 법전입니다. (수메르 법전이라는 설도 있으나 여기서는 언급하지 않겠습니다.) 고대 바빌로니아의 함무라비 왕이 제정한 법전입니다. 왜 이러한 법전을 만들게 되었을까요? 통치의 일관성이나 사회(또는 국가) 전체가 일정한 관계를 유지하기 위해서는 질서가 필요하게 되었고, 그것을 위해서 만들어진 질서가 바로 법입니다.



갑자기 법전 이야기를 왜 하냐구요? 지난 포스트에서 테스트 자동화의 철학에 따라서 어떻게 자동화할 것인지에 많은 영향을 준다는 점을 알아보았습니다.(참고 : [Test/xUnit Test Patterns] - 테스트 자동화의 철학) 이러한 상황에서 테스트 작성시 일정한 질서를 유지하기 위해서는 반드시 테스트 자동화를 위한 원칙이 존재해야 한다는 것이지요. 그래야 테스트를 읽는 사람도 유지보수를 하는 사람도 쉽게 테스트 코드에 적응을 할 수 있을테니까요.

그럼 테스트 자동화의 원칙에 대해서 하나하나 알아가보겠습니다.

1. 테스트를 먼저 작성하라.

테스트를 먼저 작성하면 디버깅을 줄여주어서 테스트 자동화에 드는 노력을 충분히 보상해줄 뿐만 아니라 테스트하기 쉬운 설계가 자연스럽게 나오게 됩니다.


2. 테스트하기 쉽게 설계하라.

테스트하기 쉽게 설계하지 않으면 나중에 테스트를 도입하는 것은 굉장한 노력이 듭니다. 레거시 코드에서 자동화 테스트를 도입하고자 하면 처음부터 테스트하기 쉽게 설계했을 때보다 훨씬 많은 노력이 듭니다.


3. 정문을 먼저 사용하라.

되도록 public으로 공개된 인터페이스를 통해서 테스트를 진행하세요. 테스트 유틸리티 등으로 리플렉션을 이용하여 데이터를 조작하거나 모의객체를 사용하여 동작 검증을 많이 한다면 결합도가 높고 깨지기 쉬운 테스트가 됩니다. 

public 인터페이스로 객체를 테스트하고 상태 검증으로 제대로 동작하는지 확인할 것을 권장합니다.


4. 의도를 드러내라.

해당 테스트가 어떠한 것을 검증하고자 하는지 의도를 들어내는 것이 중요합니다. 즉, 테스트를 읽었을 때 이것이 어떤 테스트인지 한눈에 알아볼 수 있도록 해야합니다. 그렇게 하려면 테스트코드가 길지 않아야 하며, 테스트 내에 조건문이 있어도 안됩니다. 

이를 위해서 의도가 드러나는 테스트 이름의 테스트 유틸리티 메소드를 적극적으로 사용하시기 바랍니다. 또한 테스트 메소드에서 어떤 값이 입력되서 어떤 값이 출력되는지 잘 알아볼 수 있도록 테스트 코드를 리팩토링하시는 것도 중요합니다.


5. SUT를 고치지 마라.

테스트를 효과적으로 만들기 위해서 모의 객체나 테스트를 위한 하위 클래스를 만들수 있습니다. 이 때 주의할 점은 테스트 대상이 아닌 다른 것들(다른 인터페이스를 호출하는 것)은 대체해도 되지만 테스트 대상 자체(SUT)를 변경하지는 말아야 합니다. 이를 변경하는 것은 실제 제품코드가 아닌 테스트용 제품코드를 만들어 테스트하는 것이기 때문입니다.


6. 테스트를 독립적으로 유지하라.

테스트는 혼자서 실행될 수 있어야 합니다. 통합테스트 또는 인수테스트라면 모를까 단위테스트에 있어서는 반드시 독립적으로 동작을 할 수 있어야 합니다. 단위테스트는 빠른 피드백과 작은 유지비용을 유지하여 최대한 효과를 거두는 것이 중요한대 테스트가 독립적으로 동작하지 않으면 유지비용이 커져 테스트의 효과가 반감하게 됩니다.

이를 위해서 신선한 픽스처를 설치하는 것이 중요합니다.


7. SUT를 격리하라.

테스트는 외부 환경에 영향을 받아서는 안됩니다. 외부환경에 영향을 받게 되면 테스트하기 힘들뿐만 아니라 테스트 결과의 일관성을 해치기 때문에 테스트 결과를 신뢰할 수 없게 됩니다.

예를 들어, 특정 운영체제에 종속적이거나 시간에 변화에 영향을 받는 시스템이라면 테스트는 갑자기 깨질수 있습니다. 그렇기때문에 외부 환경과 SUT(테스트 대상)을 분리하는 것이 좋습니다.

의존 주입(DI)나 모의 객체 등을 잘 이용하면 SUT를 분리하고 테스트를 좀 더 반복 가능하고 견고하게 만들 수 있습니다.


8. 겹치는 테스트를 최소화하라.

만약 테스트를 할 때 모든 조합 또는 시나리오에 대해서 테스트하기란 불가능합니다. 따라서 작성해야할 테스트를 잘 선택하는 것이 중요합니다. 필요할 경우 적절한 테스팅 기법을 동원하는 것이 좋습니다. 특정 기능에 의존하는 테스트의 수를 최대한 작게 만들어야 합니다.


9. 테스트할 수 없는 코드를 최소화하라.

공중그네타기 연습을 하는데 안전망에 구멍이 많이 뚫려있다면 연습을 하기 꺼려질 것입니다. 마찬가지로 테스트 할 수 없는 코드가 많을수록 리팩토링을 하기도 힘들어지고 버그가 발생할 확률이 높아집니다.

되도록 환경과 테스트 대상을 잘 분리하고 변하는 부분과 변하지 않는 부분을 잘 가려내서 가능한한 많은 코드가 테스트 될 수 있도록 하세요.


10. 테스트 로직을 제품 코드에 넣지 마라.

테스트는 시스템의 동작을 검증하는 행위이기 때문에 테스트 대상이 되는 시스템에 테스트 코드를 넣지 마세요. 


11. 테스트별로 하나의 조건만 검증하라.

테스트 메소드 하나에 여러가지 경우의 수를 테스트하면 테스트 의도가 드러나지 않습니다. 또한 유지보수하기도 어려워지며, 테스트를 읽는 것이 매우 힘들어지죠. 따라서 각 스크립트 기반 테스트는 반드시 한 가지 테스트 조건만 검증하길 바랍니다. 결함 국소화를 위해서라도 테스트는 한가지 조건만 검증하는 것이 좋습니다.


12. 따로 테스트 하라.

복잡한 애플리케이션은 수많은 작은 동작들을 결합하여 하나의 동작을 하기도 합니다. 이를 한꺼번에 검증하지 말고 각각의 작은 동작들을 따로따로 테스트하는 것이 중요합니다. 11번째 원칙과 마찬가지로 하나의 테스트가 너무 많은 것을 테스트하려고 해서는 안됩니다. (이는 결국 하나의 클래스가 너무 많은 책임을 지니는 것과 동일합니다.)


13. 효과와 책임을 적당하게 맞추어라.

테스트를 작성하고 수정하는 데 드는 노력이 해당 기능을 구현하는 데 드는 노력보다 더 들어서는 안됩니다. 일반적인 단위테스트이거나 DBUnit을 이용한 DAO 테스트라면 TDD를 적극적으로 이용하세요. 만약 모의객체를 이용하는 테스트라면 TDD를 사실상 하기는 힘듭니다. 이때는 구현을 먼저하세요.

테스트를 작성해서 얻는 이득이 적다면(예를 들어, 상위 레이어의 메소드를 그대로 호출하는 인터페이스와 같은 경우) 굳이 테스트를 만들 필요가 없습니다.


지금까지 테스트 자동화의 원칙에 대해서 알아보았습니다. 모든 원칙이나 패턴이 그렇듯이 무작정 지키려는 것은 의미가 없습니다. 원칙에서 요구하는 의도를 정확히 파악하고, 그 의도에 맞다고 판단이 되면 따르세요. 

빠르게 이동해야하는 고속도로에서 무작정 준법정신을 지켜 최소속도만 유지하고 간다면 교통은 마비될 것입니다. 적당히 속도를 내는 것이 현실적으로 중요합니다.(물론 법규를 지키는 한도내에서 해야겠죠 ^^)

자신만의 테스트 자동화 원칙을 세우고 그 룰에 따르시기 바랍니다.




저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > xUnit테스트패턴' 카테고리의 다른 글

테스트 자동화의 원칙  (2) 2010/06/05
테스트 자동화의 철학  (0) 2010/04/21
테스트 자동화의 목표  (0) 2010/04/14
Posted by 스쿨쥐
여러분들은 어떤 폰을 쓰고 계신가요? 제가 다니는 회사에서는 굉장히 많은 분들이 아이폰으로 바꾸셨습니다. 옆에서 보고 있으면 너무너무 탐이 날 정도로 좋은 폰이더군요. 애플은 아이폰도 모자라서 아이패드를 출시함으로써 최근에 굉장히 잘나가고 있지요.

왜 우리나라 기업들은 그런 제품을 만들지 못했을까요? 모IT 기업의 대표의 말을 빌리자면 "스티브잡스는 우리에게 문화를 선물했고, 삼성은 우리에게 광고를 선물했다. 즉, 애플의 기술이 아니라 애플의 철학에 열광한 것이다."라고 하더군요. 이처럼 경영철학은 기업의 성공에 있어서 굉장한 영향력을 가집니다.


테스트 자동화에도 철학이 중요합니다. 테스트에 관한 철학은 테스트를 어떻게 자동화할지에 대해서 많은 영향을 주기 때문입니다. xUnit 계통 테스트 자동화를 다르게 쓰는 이유가 바로 이러한 철학적인 차이 때문입니다. 예를 들어 모의 객체(Mock Object)를 잘 쓰지 않는 사람이 있는 반면 모의 객체를 자주 쓰는 사람들도 있습니다. 

그렇다면 테스트 자동화에 관련되어 어떠한 철학적 차이들이 있을까요?
  1. 테스트가 먼저냐 테스트가 나중이냐?
  2. 테스트냐 예제냐?
  3. 단계별 테스트냐 한꺼번에 테스트냐?
  4. 밖에서 안으로냐 안에서 밖으로냐?
  5. 상태검증이냐 동작검증이냐?
  6. 픽스처를 먼저 설계하냐 테스트별로 픽스처를 설계하냐?

이제부터 하나하나 비교해보겠습니다.

1. 테스트가 먼저냐 테스트가 나중이냐?

사실 이 차이는 논란이 줄어듭니다. 테스트의 경험을 쌓으면 쌓을수록 TDD 즉, 테스트를 먼저하게 됩니다. 테스트를 먼저하게 되면 테스트를 만들기 쉽고 제품코드가 간결해지며 꼭 필요한 메서드만 작성하게 됩니다. 레거시 코드에서 테스트를 작성해본 경험이 있다면 테스트를 나중에 도입하는 것이 얼마나 힘든일인지 잘 알게 됩니다.

한가지 예외가 있다면 모의 객체(Mock Object)를 사용하게 되면 테스트와 제품코드가 번갈아가며 작성되는 것을 알 수 있습니다. 하지만 이 경우에도 최초에는 테스트를 먼저 작성하게 되며, 제품코드가 추가됨에 따라 테스트에 모의 객체가 추가되는 것을 알 수 있습니다.


2. 테스트냐 예제냐?

테스트가 테스트의 의미로 작성할지 아니면 예제의 의미로서 작성할 지 분분합니다. 우리가 새로운 API나 기술셋을 익힐 때를 생각해봅시다. 아마 예제코드를 보고 따라 작성하면서 사용법을 익힐 것입니다. 이처럼 우리가 테스트를 예제로 작성한다면 테스트가 바로 "실행가능한 명세"가 되어 테스트자동화의 목표를 이루게 됩니다.

개인적인 의견으로는 처음에는 기능을 구현하여 "시스템이 돌아가는 것을 증명"하고, 버그가 발견되면 테스트를 통해 재현을 하여 "시스템이 돌아가지 않음"을 증명하면 됩니다. 결국 내가 만든 시스템이 어떠한 상황에서 돌아가고 어떻게 사용하며, 어떠한 상황에서 돌아가지 않는지에 대한 상세한 설명이 됩니다.


3. 단계별 테스트냐 한꺼번에 테스트냐?

단위테스트의 경우에는 세분화된 테스트와 점진적인 개발을 하게되면 테스트가 왜 실패했는지가 분명하기 때문에 디비거를 사용할 일이 많이 줄어듭니다.
고객테스트의 경우에는 사용자 스토리에 따른 테스트를 하나씩 제공하기가 힘듭니다. 이런 경우에는 차라리 테스트를 통하여 사용자 스토리를 구성해나가는 것이 좋습니다.


4. 밖에서 안으로냐 안에서 밖으로냐?

고객처럼 생각하기 위해서는 밖에서 안으로 설계를 해 나가는 것이 좋습니다. 하지만 테스트를 만들때마다 테스트 스텁이나 모의 객체를 써야한다는 불편한 점이 있습니다. 그래서 개인적으로는 설계는 밖에서 안으로 들어오고, 실제 구현은 안에서 밖으로 해 나가는 것이 괜찮은 방법 중 하나라고 생각합니다.


5. 상태 검증이냐 동작 검증이냐?

동작 검증은 상태 검증보다는 좀 더 세밀한 단계입니다. 동작 검증이 좋기는 하나 몇가지 단점이 있습니다. 첫째로 테스트 유지 보수 비용이 높으며, 둘째로 참조하는 인터페이스가 다른 것으로 변경되면 테스트도 쉽게 깨져버립니다. 즉, 테스트가 구현에 의존하는 경향이 나타납니다. 사실 테스트 만들기도 굉장히 귀찮지요 ^^;

그래서 개인적인 의견으로는 상태 검증을 주로 하되 동작 검증이 필요한 경우에만 추가적으로 만드는 것이 좋을 것 같습니다.


6. 픽스처를 먼저 설계하냐 테스트별로 픽스처를 설계하냐?

사실 TDD를 하다 보면 테스트 메소드별로 최소 픽스처를 사용하게 됩니다. 항상 신선한 픽스처를 사용하는 것이지요. 다만 픽스처를 먼저 설계해야 할 경우가 간혹 있습니다. 예를들어, DBUnit으로 dao를 테스트를 한다거나, 사용자 시나리오 테스트(또는 통합 테스트)를 할 경우가 있겠지요. 

꼭 필요한 부분이 아니라면 테스트 메소드별로 신선한 픽스처를 쓰는 것이 좋습니다.


지금까지 테스트 자동화에 대한 철학을 알아보았습니다. 어느 것이 맞다 틀리다의 문제가 아닙니다. 철학은 다르지만 목표는 같습니다. 높은 품질의 소프트웨어를 목적에 맞게, 제때에 개발해내는 것이지요. 다만 그 목표를 어떻게 달성할 것인지만 다를 뿐입니다. 서로 다른 철학을 이해하고 서로의 공통점을 찾아서 나아가는 것이 중요합니다.


여러분은 어떤 철학을 가지고 계시나요?

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > xUnit테스트패턴' 카테고리의 다른 글

테스트 자동화의 원칙  (2) 2010/06/05
테스트 자동화의 철학  (0) 2010/04/21
테스트 자동화의 목표  (0) 2010/04/14
Posted by 스쿨쥐
저는 어릴때부터 축구를 좋아해서 지금까지도 축구를 즐겨하고 있습니다. 흔히 말하는 "조기축구"를 하고 있지요. 다들 아시다싶이 축구는 골(goal)을 넣어야 이기는 게임입니다. 궁극적인 목적은 골을 많이 넣어서 이기는 것입니다. 


테스트도 이와 마찬가지입니다. 테스트를 왜 해야하는가는 이전글([Test] - 테스트, 정말 필요한가요?)을 참조하세요. 이번에는 테스트 자동화가 달성해야할 목표(goal)에 대해서 이야기하려 합니다.



먼저 테스트를 통해서 얻을 수 있는 가치에 대한 목표에 대해서 알아봅시다.

  1. 테스트는 품질 향상에 도움이 되어야 합니다.
  2. 테스트는 테스트 대상 시스템(System Under Test, SUT)을 이해하는 데 도움이 되어야 합니다.
  3. 테스트는 위험을 줄여야 합니다.

테스트가 품질향상에 도움이 되기 위해서는 명세로서의 테스트를 달성해야 합니다. 즉, 사용자가 SUT를 사용하는 방식을 실제 그대로 반영해야 하여야 합니다. 다른 이름으로 실행 가능한 명세라고도 합니다. 또한 회귀 테스트를 통해 버그 발생을 막아주어야 하며, 문제 범위를 좁혀서 왜 잘 돌아가지 않는지 알려주어야 합니다. 이를 결함 국소화라고 합니다.

SUT를 이해하는 데 도움이 되기 위해서는 특정 값이 입력되었을 때 어떠한 결과가 나올지를 테스트를 통해서 알려주어야 합니다. 테스트를 읽는 사람이 테스트를 문서로서 활용할 수 있도록 해야합니다. 블랙박스 컴포넌트 테스트의 경우 사실상 소프트웨어 컴포넌트의 요구 사항을 보여줍니다.

테스트를 통해서 위험을 줄일 수 있어야 합니다. 서커스에서 그물 없이 공중그네 타기를 배운다고 한다면 기술을 시도하기 무척이나 꺼려질 것입니다. 자칫 목숨이 위험할테니까요. 테스트는 이런 상황에서 안전망이 됩니다. 레거시 코드를 변경할 때 회귀 테스트를 통해서 버그가 발생할 위험을 줄여줍니다. 

반대로 그물이 공중그네 타기에 방해가 되어서는 안되겠지요. 마찬가지로 테스트가 제품코드에 해가 되지 않아야 합니다.



다음은 테스트 자체가 가져야 할 목표에 대해서 알아봅시다.

  1. 테스트는 실행하기 쉬워야 합니다.
  2. 테스트는 만들고 유지하기가 쉬워야 합니다.
  3. 테스트는 시스템이 발전해 나감에 따라 필요한 유지 보수 비용이 최소화 되어야 합니다.

테스트가 실행하기 어렵다면 아무도 테스트를 실행하지 않을 것입니다. 그래서 테스트를 쉽게 실행하기 위해서는 완전 자동으로 돌아가야 할 것이고, 직접 검사하지 않더라도 알아서 에러를 찾아내 알려줄 수 있는 자체 검사 테스트가 되어야 합니다. 그리고 몇번이고 돌려도 같은 결과가 나오는 반복되는 테스트여야 하며, 테스트별로 따로 돌려볼 수 있는 독립적인 테스트가 되어야 합니다.

테스트를 만들고 유지하는 데 많은 노력이 든다면 테스트를 작성하지 않겠지요. 그래서 테스트를 단순하게 만들어서 쉽게 만들 수 있게 하고, 테스트 유틸리티 메서드도 제공하면 더욱 좋습니다. 또한 하나의 테스트는 하나의 관심만 테스트를 하는 것이 테스트하기에도 쉬운 설계의 핵심이 됩니다.

위의 목표를 잘 달성을 했다면 시스템이 발전하는 동안에 제품코드도 변하고, 테스트 코드도 변하는 상황에서 영향을 받는 테스트의 수가 최소가 될 것입니다. 즉, 견고한 테스트가 되는 것이지요. 이렇게 되면 테스트를 유지하는 비용도 최소화가 됩니다.



인생에서 목표가 없으면 길을 잃고 해맬수 있습니다. 테스트 또한 분명한 목표를 가지고 테스트를 해야만 방향을 잃지 않고 테스트로 인한 혜택을 누릴 수 있지 않을까요?
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > xUnit테스트패턴' 카테고리의 다른 글

테스트 자동화의 원칙  (2) 2010/06/05
테스트 자동화의 철학  (0) 2010/04/21
테스트 자동화의 목표  (0) 2010/04/14
Posted by 스쿨쥐

 새해에 사람들은 많은 계획을 세우죠. 흡연자분들은 금연을 목표로 하시기도 하고, 많은 여성분들은 다이어트를 목표로 삼기도 합니다. 또한 대학 졸업자분들은 취업이 목표가 되기도 하죠. 이런 저런 목표가 많지만 그래도 꼭 빠질 수 없는 것 중 하나가 "건강"일 것입니다. 

(이미지출처)

 건강을 유지하기 위해서 운동은 언제해야 할까요? 하루 날잡아서 몰아서 하면 될까요? 조금씩 꾸준히 하는 것이 가장 좋은 방법이죠.

 테스트도 마찬가지입니다. 테스트는 항상 해야하죠. 구체적으로 다음과 같은 시점에서 하면 좋습니다.

  1. 코드를 작성하기 전 테스트를 작성합니다.(TDD)
  2. 오류가 발견되면 그 오류를 재현하기 위한 테스트를 작성합니다.
  3. 코드 사용법을 설명해야할 경우 테스트를 통해 예제를 제공합니다.
  4. 레거시코드(legacy code)에 대해서 내가 이해한 내용이 맞는지 확인할 때 테스트를 작성합니다.

 그 외에도 테스트에 대한 요구사항이 있을 경우에도 테스트를 해야합니다.

 한가지 더 말씀을 드리자면 이렇습니다. 아기 기저귀를 언제 갈아주어야 할까요? 네. 맞습니다. 아이가 오줌을 쌌거나 똥을 쌌을 때겠죠. 그럼 아기가 오줌을 쌌는지 어떻게 알 수 있나요? 바로 냄새죠. 냄새가 나면 기저귀를 갈아주면 됩니다. 

 여러분의 코드에 냄새가 나면 테스트를 하시면 됩니다.(리펙토링에서도, xUnit 테스트 패턴에서도 냄새라고 표현한 것은 이런 표현때문이죠 ^^) 어떤 냄새가 날 때 테스트 또는 리팩토링을 해야할 지는 앞으로 하나씩 다른 포스팅을 통해서 알아보겠습니다.

 건강을 지키려면 꾸준히 운동을 하고 몸관리를 해야하듯이, 우리가 만든 소프트웨어의 건강을 지키려면 꾸준히 테스트를 해야 효과가 있습니다. 

테스트, 생활화합시다!!!

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

테스트, 언제 하나요?  (0) 2010/02/04
테스트, 정말 필요한가요?  (1) 2010/02/02
버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
Posted by 스쿨쥐
얼마 전, 모 회사의 신입사원 교육을 할 기회가 생겼습니다. 여러 과목이 있었지만 저희 팀의 관심사인 "테스트"중에서 단위 테스트에 대한 강의를 진행했습니다. 이 수업을 듣기 전에 테스트에 대해서 교육을 받은 신입사원분들은 아무도 계시지 않으셨습니다. 그래서 어떻게 하면 테스트에 대한 이해를 돕고 필요성을 느끼게 할 수 있을까 고민하게 되었습니다.


테스트? 디버그?

테스트란 "비즈니스 및 기술적 요구사항을 충족하는지 검사하고, 프로그램 또는 소프트웨어의 결함(오류)이 있는지 확인하는 것"입니다. 특히 개발자에게 있어서는 자신이 만든 소스코드에 대해서 검사하는 작업이 되겠지요. 

그럼 디버그는 무엇일까요? 디버그란 "이미 발견된 결함(오류)에 대해서 원인을 분석하고 수정하는 것"을 의미합니다. 보통의 경우 이클립스를 통해서 디버그 모드로 실행하여 값을 하나하나 대조하고 어디서 값이 누락이 되거나 잘못되었는지 확인하는 것으로 디버그를 하게됩니다.


테스트와 디버그의 관계, 그리고 오해

보통의 경우 테스트를 철저할수록 디버그하는 횟수가 줄어들게 됩니다. 초보시절에는 자신의 실력을 과신한 나머지 자신의 소스가 절대 잘못될리 없다는 생각을 하게되고, 서버를 동작시킨 이후에나 잘못된 부분을 발견할 수 있었습니다. 물론 디버그 실력이 뛰어날수록 빠른 시간안에 수정할 수 있겠지요. 그 후에 이렇게 생각합니다.

"설사, 잘못된 소스라 할지라도 난 굉장히 뛰어나서 빠른 시간안에 디버그를 해서 수정할 수 있어!"라고 말이죠.

작은 프로그램을 만들고, 혼자 일을 한다면 가능할지도 모릅니다. 하지만 우리는 당연히 협업을 해야하는 상황에 놓여있고, 작은 프로그램만을 만들지는 않습니다. 또한 디버그만 잘 한다고 해서 모든 것을 해결할 수는 없으며, 사전에 예방할 수 있는 테스트의 중요성은 더욱 강조될 것입니다.


건강검진과 수술. 어느쪽을 택할 것인가?

건강검진

[건강검진]

관점을 바꾸어서 생각해봅시다. 우리 몸은 언제든 병에 걸릴 수 있습니다. 그래서 운동도 하고, 건강에 좋은 음식도 섭취합니다. 그것도 모자라 혹여나 다칠때를 대비해서 보험도 들기도 합니다. 그래도 몸이 이상이 생길까 "건강검진"도 받지요. 내 몸이 이상이 없나? 하고 말이죠.

수술

[수술]

그렇게 하더라도 병을 완전히 피할수는 없습니다. 그럴때는 어떻게 할까요? "수술"을 받게됩니다. 그리고 우리 몸이 낫게 되지요. 하지만 수술에는 큰 비용과 굉장한 휴유증을 동반하게 됩니다. 

테스트와 디버그의 관계가 바로 건강검진과 수술과의 관계와 같다고 생각합니다. 모든 병을 피할 수는 없겠지만 병에 걸릴 때까지 버티다가 "수술"로만 치료를 하는 것과 평소에 "건강검진"을 꾸준히 받으면서 몸 상태를 점검하여 병을 미리 발견하는 것에는 큰 차이가 있지요. 후자의 경우 암과 같은 큰 병을 조기에 발견해서 완치도 할 수 있을 것입니다. 마찬가지로 테스트를 통해서 사전에 소프트웨어를 점검한다면 에러가 발생할 때까지 버티다가 디버그(수술)로 치료할 때보다 훨씬 적은 비용이 발생할 것입니다.


면역성을 기르자

예방접종

[예방접종]

건강검진만으로는 조금 부족할 수 있습니다. 중요한 질병에 대해서 면역성을 갖추기 위해 우리는 예방접종을 맞기도 합니다. 예방접종의 원리는 간단합니다. 질병을 일으키는 바이러스나 세균 등의 항원이 침입하면 우리 몸에서 이에 대항하는 항체를 만듭니다. 그리고 다음에 동일한 항원이 들어오게 되면 재빨리 항체를 만들어 대응하죠. 이를 이용해 항원을 반쯤(?) 죽인 후 우리 몸에 해가 되지 않게 한 후 주입하여 항체만 만들도록 하는 것이 예방접종입니다.

이처럼 소프트웨어에 일부러 잘못된 입력 값(항원)을 주입합니다. 그리고 예외 또는 에러가 발생한다면 테스트를 작성하여 동일하게 재현하고, 수정해주세요(항체 생성) 그렇게 한다면 동일한 유형의 잘못된 입력 값(항원)으로부터 소프트웨어의 면역성을 기를 수 있습니다.


이제 여러분의 소프트웨어를 아플때까지 참지 말고 건강검진과 예방접종을 받도록 해보세요.
건강검진과 예방접종이 필요한 이유가 곧 테스트가 필요한 이유입니다. 비용도 비싸지 않습니다. 약간의 시간과 노력만 들인다면 얼마든지 건강해질 수 있습니다.

여러분의 소프트웨어는 건강하십니까?


저작자 표시 비영리 동일 조건 변경 허락
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

테스트, 언제 하나요?  (0) 2010/02/04
테스트, 정말 필요한가요?  (1) 2010/02/02
버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
Posted by 스쿨쥐
1. 버그를 식별한다.
2. 버그가 있는 것을 증명하기 위해서 실패하는 테스트를 작성한다.
3. 코드를 수정한다.
4. 모든 테스트를 확인한다. 수정작업으로 인하여 다른 것이 변경되었는지 확인하기 위해서 모든 테스트를 확인한다.
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

테스트, 언제 하나요?  (0) 2010/02/04
테스트, 정말 필요한가요?  (1) 2010/02/02
버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
Posted by 스쿨쥐
1. 자동적(Automatic)
  - 테스트를 실행하는 경우와 결과를 확인하는 경우 모두 자동으로 실행되어야 한다.

2. 철저함(Thorough)
  - 성공케이스, 경계조건 검사, 테스트 커버리지 등 되도록이면 문제가 될 수 있는 모든 것을 테스트한다.
  - 프로젝트의 요구사항에 따라 철저함의 범위를 조절해야 한다.

3. 반복 가능(Repeatable)
  - 각각의 테스트는 독립적이어야 하고, 어떤 순서로든 여러 번 반복 실행이 될 수 있어야 하며, 항상 같은 결과를 나타내야 한다.
  - 외부 환경에 의존해서 테스트를 해서는 안된다.

4. 독립적(Independent)
  - 어떠한 테스트도 다른 테스트에 의존하지 않아야 한다.
  - 모든 테스트는 섬이어야 한다.

5. 전문적(Professional)
  - 좋은 설계를 위한 모든 일반적인 규칙, 캡슐화 유지, DRY 원칙 지키기, 결합도 낮추기 등은 제품 코드에서 그랬듯이 테스트 코드에서도 반드시 지켜져야 한다.
  - 단순 getter, setter에 대한 테스트에 시간낭비 하지 마라. (즉, 로직이 있는 것에 집중하라.)
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

테스트, 정말 필요한가요?  (1) 2010/02/02
버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
단위 테스트의 목적  (0) 2009/06/15
Posted by 스쿨쥐
2009/07/01 22:09

테스트 대상 테스트기법/단위테스트2009/07/01 22:09

1. 결과가 옳은가(right)?
  - 이 코드가 옳게 동작한다면 그것을 어떻게 알 수 있는가? 에 대한 대답이 되는 테스트 코드를 작성해야 한다.

2. 경계조건
  - 형식 일치(Conformance) : 값의 형식이 기대한 형식과 일치하는가?
  - 순서(Ordering) : 적절히 순서대로 되어 있거나 그렇지 않은 값인가?
  - 범위(Range) : 적당한 최소값과 최대값 사이에 있는 값인가? 인덱스 값이 적절한가?
  - 참조(Reference) : 코드가 자기가 직접 제어하지 않는 외부 코드를 참조하는가? 사전조건(파라미터가 null 또는 0, 0.0, "" 등) 또는 사후조건("", not null 보장여부, empty value 등)이 어떻게 되는가?
  - 존재성(Existence) : 값이 존재하는가? (not null, 0 또는 0.0이 아님, ""이 아님, 빈 컬렉션 객체가 아님 등)
  - 개체 수(Cardinality) :확실히 충분한 값이 존재하는가? 0-1-N 규칙
  - 시간(Time) : 상대시간(시간적 순서), 절대시간(경과한 총 시간), 동시성(concurrency) 문제

3. 논리역 적용 검증
  - 논리역(inverse)을 적용하여 검증한다.
  - DB insert의 경우는 select를 통해서 찾아본다.
  - 제곱근을 구하는 메서드의 경우 결과값을 제곱하여 원래의 값과 오차 범위 안에서 같은지 테스트를 하면 된다.

4. 다른 수단을 이용한 교차 확인
  - 서로 다른 알고리즘을 사용하여 값이 동일한지 확인한다.
  - 전체 = A + B 임을 적용하여 확인한다. 예를들어 전체관람석수 = 판매된 관람석 + 판매가능 관람석이다.
 
5. 에러 조건을 강제로 만들어내기
  - 모의객체(mock object)를 사용하여 특정 에러 상황을 재현한다.
  - 메모리 부족, 디스크 공간 부족, 시간제한, 네트워크 부하 및 에러, 시스템 부하, 색상 제한, 해상도 제한 등

6. 성능특성
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
단위 테스트의 목적  (0) 2009/06/15
단위 테스트란?  (0) 2009/06/15
Posted by 스쿨쥐
1. 테스트에 필요한 모든 조건과 상황을 준비 설정한다. (필요한 객체를 모두 생성하기, 필요한 자원을 모두 할당하기 등)

2. 테스트 대상이 되는 메서드를 호출한다.

3. 테스트 대상이 되는 메서드가 원하는 대로 동작한다는 것을 검증한다.

4. 실행이 끝나고 다른 코드에 영향이 없게 정리 작업을 한다.
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
단위 테스트의 목적  (0) 2009/06/15
단위 테스트란?  (0) 2009/06/15
Posted by 스쿨쥐

1. 내가 원하는 일을 하는가?

2. 언제나 내가 원하는 일을 하는가?

3. 내가 의존할 수 있는가?
 - 코드의 능력과 한계를 정확히 알 수 있으면 된다.

4. 내 의도를 문서화하고 있는가?
 - 개발자가 다양한 조건 하에서 어떻게 코드가 동작할 것을 기대했는지 보여주는, 실행 가능한 문서화 역할을 한다. 팀원들은 테스트를 보고 코드의 사용방법을 알 수 있다.
저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'테스트기법 > 단위테스트' 카테고리의 다른 글

버그를 고치는 방법  (0) 2009/08/13
좋은 테스트의 특징  (0) 2009/08/13
테스트 대상  (0) 2009/07/01
단위 테스트 구조화  (0) 2009/06/24
단위 테스트의 목적  (0) 2009/06/15
단위 테스트란?  (0) 2009/06/15
Posted by 스쿨쥐