Home 랜덤 값에 따라 다르게 동작하는 메서드를 테스트하는 방법
Post
Cancel

랜덤 값에 따라 다르게 동작하는 메서드를 테스트하는 방법

테스트 코드를 작성하다 보면 랜덤 값에 의해 다르게 작동하는 메서드를 테스트해야 하는 경우가 있다.

예를 들어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Game {
	private int position;

	public void move() {
		if (canMove()) {
			position++;
		}
	}
	
	private boolean canMove() {
		return 5 < RandomNumberGenerator.generate(0,9);
	}
}

위 게임은 0~9까지의 랜덤값을 뽑고 그 수가 5보다 크다면 position을 1씩 증가시킬 수 있는 게임이다.

이 때 move() 메서드에서 랜덤 값에 의해 position의 변화가 이루어지기 때문에 테스트를 진행하는데 어려움이 생긴다. 값이 랜덤이면 move()에 의해 position에 변동이 있는지, 없는지 알 수 없기 때문이다.

이렇게 되면 테스트는 어쩔때는 성공하고, 실패하게 되는 것이다.

랜덤값에 의한 메서드 테스트 해결방법

RandomNumberGenerator와 Game은 지금 강하게 결합되어 있다. 이 결합을 분리하여 테스트를 진행할 수 있도록 수정하면 된다.

  • RandomUtil 인터페이스를 만든다.
  • 랜덤값을 생성하는 객체(RandomNumberGenerator)를 RandomUtil의 구현체로 만든다.
  • 이 구현체를 Game은 주입받아 사용하도록 수정한다.

인터페이스 생성

1
2
3
public interface RandomUtil {  
	int generate(int min, int max);  
}

참고로 인터페이스를 생성해야 아래 테스트 코드의 람다식 형태를 사용할 수 있다.

구현체로 하면 new RandomNumberGenerator()를 넣어주어야 해 람다식 형태는 사용할 수 없다.

RandomNumberGenerator 구현체 생성

1
2
3
4
5
6
7
public class RandomNumberGenerator implements RandomUtil {  
	@Override  
	public int generate(int min, int max) {  
		return Randoms.pickNumberInRange(min, max);  
		//min, max 범위 내에서 랜덤값을 추출한다.
	}  
}

Game이 주입받아 사용하도록 수정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Game {
	private int position;
	private RandomUtil randomUtil;

	public Game(int position, RandomUtil randomutil) {
		this.position = position;
		this.randomUtil = randomUtil;
	}

	public void move() {
		if (canMove()) {
			position++;
		}
	}
	
	private boolean canMove() {  
		return 5 < randomUtil.generate(0,9);  
	}
}

테스트 코드

위와 같은 수정을 통해 랜덤값의 값을 고정시켜 테스트할 수 있게 된다.

1
2
3
4
5
6
7
8
@Test
public void moveTest() {
	Game game = new Game(1, (min, max) -> 6);
	
	game.move();
	
	assertThat(game).extracting("position").isEqualTo(2);
}

(min,max) -> 6 은 RandomUtil 인터페이스의 generate 메서드를 구현한 람다 표현식이 된다.

어떤 min과 max값을 전달해도 항상 6을 반환하게 된다.

랜덤 값을 6으로 지정했으므로 game의 move 메서드를 실행하면 항상 position을 1 증가시키게 되는 것이고 위의 테스트가 성공하게 되는 것이다.

This post is licensed under CC BY 4.0 by the author.