- 자바 플레이그라운드 with TDD, 클린코드 강의 내용을 실습한 내용입니다.
- 0️⃣ 학습테스트 실습에 해당합니다.
package study;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class StringTest {
@Test
void replace() {
String actual = "abc".replace("b", "d");
assertThat(actual).isEqualTo("adc");
}
}
힌트
- 나의 풀이
두 번째 힌트인 containsExactly()는 순서를 포함하여 정확하게 원소가 일치하는 것을 찾는다. 중복 값이 있어도 안되고 순서가 달라져도 안된다. 특정 자료 구조의 정확한 값을 테스트해야 할 때 이 메서드를 사용할 수 있다.
@Test
void split() {
String[] actual1 = "1".split(",");
assertThat(actual1).contains("1");
System.out.println(Arrays.toString(actual1));
String[] actual2 = "1,2".split(",");
assertThat(actual2).contains("1","2");
assertThat(actual2).containsExactly("1","2");
System.out.println(Arrays.toString(actual2));
}
- 나의 풀이
// 테스트 요구사항
// "(1,2)" 값이 주어졌을 때 String의 substring() 메소드를 활용해 ()을 제거하고 "1,2"를 반환하도록 구현한다.
@Test
void substring() {
String actual = "(1,2)";
actual = actual.substring(1);
actual = actual.substring(0,3);
System.out.println(actual);
assertThat(actual).isEqualTo("1,2");
}
substring()은 시작과 끝을 지정하여 문자열을 자를 수 있는 메서드다. ()안에 잘라낸 위치를 정할 수 있다.
String.substring(start) //문자열 start index부터 끝까지 문자열 자른다.
String.substring(start,end) //문자열 start index부터 end index까지 문자열을 발췌한다.
(1,2)라는 문자열은 index 0~4 까지 ( 1 , 2 )로 구성된 char 배열과 같다. 해당 위치를 index로 지정하여 자르는 것이 ( )에 해당하는 문자열을 잘라내는 가장 간단한 방법이라고 생각했다. 앞의 "("와 뒤의 ")"를 잘라내야 하기 때문에 두 번 작업이 필요하다.
첫번째 괄호는 0번을 잘라내고 1번 문자열부터 끝까지를 발췌하는 방법으로 제거하였고, 두번째 괄호는 0번부터 3번까지 문자열을 발췌하는 방법으로 제거하였다.
힌트
나의 풀이
IndexOutOfBoundsException
발생 시Exception
의 인스턴스 타입이 일치하면 메시지를 출력한다.
// 테스트 요구사항 3
// "abc" 값이 주어졌을 때 String의 charAt() 메소드를 활용해 특정 위치의 문자를 가져오는 학습 테스트를 구현한다.
// String의 charAt() 메소드를 활용해 특정 위치의 문자를 가져올 때 위치 값을 벗어나면
// StringIndexOutOfBoundsException이 발생하는 부분에 대한 학습 테스트를 구현한다.
// JUnit의 @DisplayName을 활용해 테스트 메소드의 의도를 드러낸다
@Test
@DisplayName("예외 발생 테스트")
void charAt() {
assertThatThrownBy(() -> {
String actual = "abc";
System.out.println(actual.charAt(2));
throw new IndexOutOfBoundsException("boom!");
}).isInstanceOf(IndexOutOfBoundsException.class)
.hasMessageContaining("인덱스 범위를 초과했습니다.");
}
자주 발생하는 Exception의 경우 Exception별 메서드 제공하고 있음.
public class SetTest {
private Set<Integer> numbers;
@BeforeEach
void setUp() {
numbers = new HashSet<>();
numbers.add(1);
numbers.add(1);
numbers.add(2);
numbers.add(3);
}
// Test Case 구현
}
나의 풀이
- setUp()가
@beforeEach
되어 있으므로, 모든 테스트 메서드 실행 전 실행된다.- setUp()이 실행되면서 생성된 numbers 인스턴스의 size를 출력하여 확인했다.
public class SetCollectionTest {
// Set Collection에 대한 학습 테스트
// 다음과 같은 Set 데이터가 주어졌을 때 요구사항을 만족해야 한다.
private Set<Integer> numbers;
@BeforeEach
void setUp() {
numbers = new HashSet<>();
numbers.add(1);
numbers.add(1);
numbers.add(2);
numbers.add(3);
}
// Test Case 구현
// 요구사항 1
// Set의 size() 메소드를 활용해 Set의 크기를 확인하는 학습테스트를 구현한다.
@Test
@DisplayName("Set 사이즈 확인")
void setSize() {
System.out.println(numbers.size());
}
}
contains()
메소드를 활용해 1, 2, 3의 값이 존재하는지를 확인하는 학습테스트를 구현하려한다.나의 풀이
@ParameterizedTest
를 사용하면 여러개의 파라미터 값을 순차적으로 테스트 할 수 있다.
파라미터에 넣을 값은@ValueSource
에 배열의 형태로 넣으면 된다.
// 요구사항 2
// Set의 contains() 메소드를 활용해 1, 2, 3의 값이 존재하는지를 확인하는 학습테스트를 구현하려한다.
// 구현하고 보니 다음과 같이 중복 코드가 계속해서 발생한다.
// JUnit의 ParameterizedTest를 활용해 중복 코드를 제거해 본다.
@DisplayName("assertThat 중복 코드 제거하기")
@ParameterizedTest
@ValueSource(ints = {1,2,3})
void contains(int number) {
assertThat(numbers.contains(number)).isTrue();
}
힌트
@ParameterizedTest
@CsvSource(value = {"test:test", "tEst:test", "Java:java"}, delimiter = ':')
void toLowerCase_ShouldGenerateTheExpectedLowercaseValue(String input, String expected) {
String actualValue = input.toLowerCase();
assertEquals(expected, actualValue);
}
나의 풀이
CsvSource
를 이용해 예상되는 결과 값을 쌍으로 준비했다.
테스트 메서드의 파리미터로CsvSource
에 쌍으로 들어가 있는 input:expected 값을 순차적으로 받는다.
Contain()
을 이용해 numbers Set에 input에 해당하는 값이 포함되어 있는지 확인한다. 문자열을 숫자로 타입 캐스팅했다.
assertEquals()
를 이용해 expected 값과 실제 값을 비교했다.
// 요구사항 3
// 요구사항 2는 contains 메소드 결과 값이 true인 경우만 테스트 가능하다. 입력 값에 따라 결과 값이 다른 경우에 대한 테스트도 가능하도록 구현한다.
// 예를 들어 1, 2, 3 값은 contains 메소드 실행결과 true, 4, 5 값을 넣으면 false 가 반환되는 테스트를 하나의 Test Case로 구현한다.
// 힌트
// Guide to JUnit 5 Parameterized Tests 문서에서 @CsvSource를 활용한다.
@ParameterizedTest
@CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':')
void contains123(String input, String expected) {
boolean actualNum = numbers.contains(Integer.parseInt(input));
System.out.println(actualNum);
assertEquals(Boolean.parseBoolean(expected), actualNum);
}