답변:
소스를 연결하는 것으로 시작하겠습니다 -JUnit을 사용하는 Java의 Pragmatic Unit Testing (C # -Nunit도 포함 된 버전도 있지만이 버전도 있습니다. 대부분의 경우 불가지론 적입니다. 권장 됨)
Good Tests는 A TRIP 이어야합니다 (약어가 충분히 끈적 거리지 않습니다. 책에 치트 시트가 인쇄되어있어이 문제가 올바른지 확인해야했습니다 ..)
전문가가 : 장기적으로 당신은 그러므로 테스트 코드에 대한 좋은 디자인의 동일한 표준에 따라 생산 한 많은 테스트 코드 (안 많은 경우)로해야합니다. 의도를 드러내는 이름, 중복 없음, 좋은 이름의 테스트 등을 가진 잘 팩터링 된 메서드 클래스
좋은 테스트도 빠르게 실행 됩니다. 실행하는 데 0.5 초 이상 걸리는 모든 테스트를 수행해야합니다. 테스트 스위트를 실행하는 데 시간이 오래 걸릴수록 실행 빈도가 줄어 듭니다. 더 많은 변경 사항이있을수록 개발자는 실행 사이에 몰래 들어 가려고합니다. 어떤 것이 깨지면 .. 어떤 변경이 원인인지 알아내는 데 시간이 더 오래 걸립니다.
2010-08 업데이트 :
이 외에도 대부분의 다른 것들은 저수익 작업을 줄이는 지침입니다. 예 : '소유하지 않는 코드는 테스트하지 마십시오'(예 : 타사 DLL). 게터와 세터를 테스트하지 마십시오. 비용 대 이익 비율 또는 결함 가능성을 주시하십시오.
여기에있는 대부분의 답변은 실제로 테스트 자체 (어떻게)를 작성하는 것이 아니라 일반적으로 (언제, 어디서, 왜, 무엇을) 단위 테스트 모범 사례를 다루는 것 같습니다. 질문이 "어떻게"부분에 대해 매우 구체적으로 보였기 때문에, 나는 회사에서 실시한 "갈색 가방"프레젠테이션에서 가져온 이것을 게시 할 것이라고 생각했습니다.
1. 길고 설명적인 테스트 방법 이름을 사용합니다.
- Map_DefaultConstructorShouldCreateEmptyGisMap()
- ShouldAlwaysDelegateXMLCorrectlyToTheCustomHandlers()
- Dog_Object_Should_Eat_Homework_Object_When_Hungry()
2. Arrange / Act / Assert 스타일로 테스트를 작성합니다 .
3. 항상 어설 션과 함께 실패 메시지를 제공하십시오.
Assert.That(x == 2 && y == 2, "An incorrect number of begin/end element
processing events was raised by the XElementSerializer");
4. 테스트 이유를 설명하십시오 . 비즈니스 가정은 무엇입니까?
/// A layer cannot be constructed with a null gisLayer, as every function
/// in the Layer class assumes that a valid gisLayer is present.
[Test]
public void ShouldNotAllowConstructionWithANullGisLayer()
{
}
5. 모든 테스트는 항상 접촉하는 리소스의 상태를 되돌려 야합니다.
이러한 목표를 염두에 두십시오 (Meszaros의 xUnit Test Patterns 책에서 수정 됨).
더 쉽게 할 수있는 몇 가지 사항 :
당신도 당신의 xUnit의 프레임 워크 intergration 테스트를 할 수 있다는 것을 잊지 마세요 하지만 intergration 테스트 및 단위 테스트를 별도로 보관
훌륭한 단위 테스트의 몇 가지 속성 :
테스트가 실패하면 문제가 어디에 있는지 즉시 알 수 있어야합니다. 디버거를 사용하여 문제를 추적해야하는 경우 테스트가 충분히 세분화되지 않은 것입니다. 테스트 당 단 하나의 주장 만 있으면 도움이됩니다.
리팩터링 할 때 테스트가 실패해서는 안됩니다.
테스트는 너무 빨리 실행되어 주저하지 않아야합니다.
모든 테스트는 항상 통과해야합니다. 비 결정적 결과가 없습니다.
단위 테스트는 프로덕션 코드와 마찬가지로 잘 구성되어야합니다.
@Alotor : 라이브러리에 외부 API에서만 단위 테스트가 있어야한다고 제안하는 경우 동의하지 않습니다. 외부 호출자에게 노출하지 않는 클래스를 포함하여 각 클래스에 대한 단위 테스트를 원합니다. (그러나 프라이빗 메서드에 대한 테스트를 작성해야한다고 생각되면 리팩토링해야합니다. )
편집 : "테스트 당 하나의 주장"으로 인한 중복에 대한 의견이있었습니다. 특히 시나리오를 설정하기위한 코드가 있고 이에 대해 여러 개의 어설 션을 만들고 싶지만 테스트 당 하나의 어설 션 만있는 경우 여러 테스트에서 설정을 복제 할 수 있습니다.
나는 그 접근 방식을 취하지 않습니다. 대신 시나리오별로 테스트 픽스처를 사용 합니다. 다음은 대략적인 예입니다.
[TestFixture]
public class StackTests
{
[TestFixture]
public class EmptyTests
{
Stack<int> _stack;
[TestSetup]
public void TestSetup()
{
_stack = new Stack<int>();
}
[TestMethod]
[ExpectedException (typeof(Exception))]
public void PopFails()
{
_stack.Pop();
}
[TestMethod]
public void IsEmpty()
{
Assert(_stack.IsEmpty());
}
}
[TestFixture]
public class PushedOneTests
{
Stack<int> _stack;
[TestSetup]
public void TestSetup()
{
_stack = new Stack<int>();
_stack.Push(7);
}
// Tests for one item on the stack...
}
}
당신이 추구하는 것은 테스트중인 클래스의 행동을 묘사하는 것입니다.
기본적인 의도는 수업의 행동에 대한 자신감을 높이는 것입니다.
이는 코드를 리팩토링 할 때 특히 유용합니다. Martin Fowler는 그의 웹 사이트에서 테스트에 관한 흥미로운 기사 를 가지고 있습니다.
HTH.
건배,
Rob
테스트는 원래 실패해야합니다. 그런 다음 통과하는 코드를 작성해야합니다. 그렇지 않으면 버그가 발생하고 항상 통과하는 테스트를 작성할 위험이 있습니다.
앞서 언급 한 Pragmatic Unit Testing 책 의 Right BICEP 약어를 좋아합니다 .
개인적으로 나는 당신이 올바른 결과를 얻었는지 확인하고 (1 + 1은 덧셈 함수에서 2를 반환해야 함), 당신이 생각할 수있는 모든 경계 조건을 시도함으로써 꽤 멀리 갈 수 있다고 생각합니다. 더하기 함수의 정수 최대 값보다 큽니다) 네트워크 장애와 같은 오류 조건을 강제합니다.
좋은 테스트는 유지 관리가 가능해야합니다.
복잡한 환경에서이 작업을 수행하는 방법을 알지 못했습니다.
코드베이스가 수백 천 또는 수백만 줄의 코드에 도달하기 시작하면 모든 교과서가 풀리기 시작합니다.
좋은 아키텍처는 상호 작용 폭발의 일부를 제어 할 수 있지만 시스템이 더욱 복잡 해짐에 따라 자동화 된 테스트 시스템도 함께 성장합니다.
여기서 트레이드 오프를 처리해야합니다.
다음 사항도 결정해야합니다.
코드베이스에서 테스트 케이스를 어디에 저장합니까?
나는 영원히 계속할 수 있지만 내 요점은 다음과 같습니다.
테스트는 유지 보수가 가능해야합니다.
저는 이 MSDN Magazine 기사 에서 이러한 원칙을 다루었습니다.이 기사 는 모든 개발자에게 중요하다고 생각합니다.
"좋은"단위 테스트를 정의하는 방법은 다음과 같은 세 가지 속성을 가지고 있는지 여부입니다.
Jay Fields는 단위 테스트 작성에 대한 좋은 조언을 많이 가지고 있으며 그가 가장 중요한 조언을 요약 한 게시물이 있습니다. 거기에서 당신은 당신의 맥락에 대해 비판적으로 생각하고 조언이 당신에게 가치가 있는지 판단해야한다는 것을 읽을 것입니다. 여기에서 놀라운 답변을 얻을 수 있지만 상황에 가장 적합한 것은 사용자가 결정해야합니다. 시도해보고 나쁜 냄새가 나면 리팩토링하십시오.
감사합니다
나는 두 번째로 "A TRIP"대답을했는데, 테스트는 서로 의존해야 한다는 점을 제외하면 !!!
왜?
DRY-반복하지 마십시오-테스트에도 적용됩니다! 테스트 종속성은 1) 설정 시간을 절약하고, 2) 픽스처 리소스를 절약하고, 3) 오류를 정확히 파악하는 데 도움이 될 수 있습니다. 물론 테스트 프레임 워크가 최고 수준의 종속성을 지원하는 경우에만 가능합니다. 그렇지 않으면 나쁘다는 것을 인정합니다.
종종 단위 테스트는 모의 객체 또는 모의 데이터를 기반으로합니다. 세 종류의 단위 테스트를 작성하고 싶습니다.
요점은 모든 기능을 테스트 할 수 있도록 모든 것을 재생하지 않는 것 입니다.
저는 Roy Osherove의 단위 테스트 명명 표준에 설명 된 일관된 테스트 명명 규칙을 사용합니다 . 주어진 테스트 케이스 클래스의 각 메서드에는 다음과 같은 명명 스타일 MethodUnderTest_Scenario_ExpectedResult가 있습니다.
각 섹션은 Upper Camel Case를 사용하며 언더 스코어로 구분됩니다.
테스트를 실행할 때 이것이 유용하다는 것을 알았습니다. 테스트는 테스트중인 메소드의 이름으로 그룹화됩니다. 그리고 규칙을 통해 다른 개발자가 테스트 의도를 이해할 수 있습니다.
또한 테스트중인 메서드가 오버로드 된 경우 메서드 이름에 매개 변수를 추가합니다.