테스트중인 대상에 따라 다릅니다. 그러나 테스트의 범위가 자신의 코드 일 뿐이라고 가정 해 봅시다. 이 경우 다음을 테스트해야합니다.
- "행복한 사례": 응용 프로그램에 유효한 입력을 제공하고 올바른 출력을 생성하는지 확인하십시오.
- 실패 사례 : 애플리케이션에 유효하지 않은 입력을 제공하고 올바르게 처리하는지 확인하십시오.
이렇게하려면 동료의 구성 요소를 사용할 수 없습니다. 대신 mocking을 사용 하십시오. 즉, 나머지 응용 프로그램을 테스트 프레임 워크에서 제어 할 수있는 "가짜"모듈로 바꿉니다. 이 작업을 정확히 수행하는 방법은 모듈의 인터페이스 방식에 따라 다릅니다. 하드 코딩 된 인수로 모듈의 메소드를 호출하는 것으로 충분할 수 있으며 다른 모듈의 공용 인터페이스를 테스트 환경과 연결하는 전체 프레임 워크를 작성하는 것처럼 복잡 할 수 있습니다.
그러나 그것은 단지 단위 테스트 사례입니다. 또한 모든 모듈을 함께 테스트하는 통합 테스트가 필요합니다. 다시 한 번, 행복한 사례와 실패를 모두 테스트하려고합니다.
"기본 예제"의 경우 코드를 단위 테스트하려면 데이터베이스 계층을 시뮬레이트하는 모의 클래스를 작성하십시오. 모의 클래스는 실제로 데이터베이스로 이동하지 않습니다. 예상 입력 및 고정 출력으로 미리로드하십시오. 의사 코드에서 :
function test_ValidUser() {
// set up mocking and fixtures
userid = 23;
db = new MockDB();
db.fixedResult = { firstName: "John", lastName: "Doe" };
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
expectedResult = "John Doe";
// run the actual test
actualResult = userController.displayUserAsString(userid);
// check assertions
assertEquals(expectedResult, actualResult);
db.assertExpectedCall();
}
다음은 올바르게 보고 된 누락 된 필드를 테스트하는 방법입니다 .
function test_IncompleteUser() {
// set up mocking and fixtures
userid = 57;
db = new MockDB();
db.fixedResult = { firstName: "John", lastName: "NA" };
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
// let's say the user controller is specified to leave "NA" fields
// blank
expectedResult = "John";
// run the actual test
actualResult = userController.displayUserAsString(userid);
// check assertions
assertEquals(expectedResult, actualResult);
db.assertExpectedCall();
}
이제 상황이 재미있어집니다. 실제 DB 클래스가 제대로 작동하지 않으면 어떻게됩니까? 예를 들어, 불명확 한 이유로 예외가 발생할 수 있습니다. 우리는 그것이 있는지 알지 못하지만 자체 코드가 정상적으로 처리하기를 원합니다. 문제 없습니다. 예를 들어 다음과 같은 메소드를 추가하여 MockDB에서 예외를 발생시켜야합니다.
class MockDB {
// ... snip
function getUser(userid) {
if (this.fixedException) {
throw this.fixedException;
}
else {
return this.fixedResult;
}
}
}
그런 다음 테스트 사례는 다음과 같습니다.
function test_MisbehavingUser() {
// set up mocking and fixtures
userid = 57;
db = new MockDB();
db.fixedException = new SQLException("You have an error in your SQL syntax");
db.expectedCall = { method: 'getUser', params: { userid: userid } };
userController = new UserController(db);
// run the actual test
try {
userController.displayUserAsString(userid);
}
catch (DatabaseException ex) {
// This is good: our userController has caught the raw exception
// from the database layer and wrapped it in a DatabaseException.
return TEST_PASSED;
}
catch (Exception ex) {
// This is not good: we have an exception, but it's the wrong kind.
testLog.log("Found the wrong exception: " + ex);
return TEST_FAILED;
}
// This is bad, too: either our mocking class didn't throw even when it
// should have, or our userController swallowed the exception and
// discarded it
testLog.log("Expected an exception to be thrown, but nothing happened.");
return TEST_FAILED;
}
이것들은 단위 테스트입니다. 통합 테스트의 경우 MockDB 클래스를 사용하지 않습니다. 대신 실제 클래스를 모두 연결합니다. 여전히 비품이 필요합니다. 예를 들어 테스트를 실행하기 전에 테스트 데이터베이스를 알려진 상태로 초기화해야합니다.
이제 책임이있는 한 : 코드는 나머지 코드베이스가 사양에 따라 구현 될 것으로 예상해야하지만 나머지 코드가 고정 될 때도 정상적으로 처리 할 수 있도록 준비해야합니다. 귀하는 자신의 코드가 아닌 다른 코드를 테스트 할 책임 이 없지만, 코드의 반대쪽에있는 코드를 복원력있게 만드는 책임은 물론 코드의 탄력성을 테스트 할 책임도 있습니다. 그것이 위의 세 번째 테스트가하는 것입니다.