17. 불확실성(non-deterministic)
• 외부세상에서 값 읽어오기
• 랜덤수 / 임의시각
• 전역변수
• 로컬머신에 존재하는 파일 내용
• 데이터베이스의 특정 레코드
• HTTP - GET
장애물1
public string GetAMOrPM()
{
var now = DateTime.Now;
if (now.Hour < 12)
{
return "AM";
}
else
{
return "PM";
}
}
18. 부수효과(side-effect)
• 외부세상의 값을 변경
• 전역변수
• 로컬머신에 존재하는 파일 내용
• 데이터베이스의 특정 레코드
• HTTP - POST
장애물2
Arrange
Act
Assert
SUT
(테스트 대상)
Database
19. 순수함수(pure function)
• 불확실성: 외부세상에서 값을 읽어오는 것과 관련
• 부수효과: 외부세상에 값을 기록하는 것과 관련
• 불확실성과 부수효과가 없는 것을 순수함수라 함
테스트하기 쉬운 코드외부 세상과 단절된 상태
20. 리턴 타입 별 Testability
• 리턴 타입이 없는 경우
public void Add(int x, int y)
{
... // 외부세상을 변경하는 코드
}
21. 리턴 타입 별 Testability
• 리턴 타입이 있는 경우
외부세상을 변경하는 코드 존재
public int Add(int x, int y)
{
var result = x + y;
Console.WriteLine(result);
return result;
}
Non-testable
22. 리턴 타입 별 Testability
• 리턴 타입이 있는 경우
public int Add(int x, int y)
{
var result = x + y;
return result;
}
23. 리턴 타입 별 Testability
• 리턴 타입이 있는 경우
public int Add(int x, int y)
{
int result = MathApiClient.GetAdd(x, y);
return result;
}
하지만 외부세상에 의존하면?
24. 외부세상에 의존하지 않고
값을 리턴하는 경우
테스트하기 쉬운 코드란?
하스켈: IO<T>
C#: Task<T>
자바: Future<T>
25. IO<T>를 리턴하지 않으면서 Non-testable한 경우도 있지만(eg. 랜덤수),
큰 틀에서 IO<T>를 리턴하는 경우를 Non-testable 이다고 할 수 있음.
26. 예제 시나리오(회원가입)
1. 입력된 이메일 형식을 검사한다.
2. 입력된 비밀번호 형식을 검사한다.
3. 정보를 DB에 저장하고 회원가입을 완료한다.
27. public async Task SignUp(string email, string password)
{
// 이메일이 유효한지 검사합니다.
if (!email.Contains("@"))
throw new ArgumentException("유효한 이메일 형식이 아닙니다.");
...
// 비밀번호가 유효한지 검사합니다.
if (password.Length < 8)
throw new ArgumentException("비밀번호는 최소 8자리 이상입니다.");
...
await UserStore.AddAsync(email, passwod);
}
테스트하기 쉬운 코드입니까?
28. Non-testable 무엇이 문제입니까?
public async Task SignUp(string email, string password)
{
// 이메일이 유효한지 검사합니다.
if (!email.Contains("@"))
throw new ArgumentException("유효한 이메일 형식이 아닙니다.");
...
// 비밀번호가 유효한지 검사합니다.
if (password.Length < 8)
throw new ArgumentException("비밀번호는 최소 8자리 이상입니다.");
...
await UserStore.AddAsync(email, passwod);
}