• μλ νμΈμ~ μ΄μ μ μ΄μνλ λΈλ‘κ·Έ λ° GitHub, κ³΅λΆ λ΄μ©μ μ 리νλ Study-GitHub κ° μμ΅λλ€!
• π
π JUnit5 - @ParameterizedTest, @ValueSource, @CsvSource, @MethodSource
μλ νμΈμ! μ΄λ² μκ°μ μ 리ν λ΄μ©μ JUnitμμ νλΌλ―Έν°μ ν μ€νΈμ κ΄λ ¨λ λ€μν ν μ€νΈ λ°©λ²μ λλ€.
μ΄λ²μ λ₯μ€νΈμ€ν μμ μ§ννλ μλ° νλ μ΄κ·ΈλΌμ΄λ κ³Όμ μ λ€μΌλ©΄μ ν μ€νΈ μ½λλ₯Ό μμ±νκ³ μλλ°μ,
μ΄μ κ΄λ ¨ν΄ νλΌλ―Έν°μ μ€λ³΅ κ°μ λν ν μ€νΈ μ½λλ₯Ό μ κ±°νκ±°λ, μ λ ₯ κ°μ λ°λΌ κ²°κ³Ό κ°μ΄ λ€λ₯Έ κ²½μ°λ ν μ€νΈκ° κ°λ₯νλλ‘ κ΅¬ννλ κ³Όμ μμ μμ μ΄λ Έν μ΄μ μ μ¬μ©νκ² λμλλ°μ, κ°λ΅νκ² μ 리ν΄λ³΄λλ‘ νκ² μ΅λλ€.
λ¨Όμ ν΄λΉ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νκΈ° μν΄ μμ‘΄μ±μ μΆκ°ν©λλ€.
Maven - pom.xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
Gradle - build.gradle
testCompile("org.junit.jupiter:junit-jupiter-params:5.7.0")
* μ°Έκ³ λ‘ νμ¬ μ κ° μ¬μ©νκ³ μλ Gradleμ λνλμλ λ€μκ³Ό κ°μ΅λλ€.
dependencies {
testImplementation "org.junit.jupiter:junit-jupiter:5.7.2"
testImplementation "org.assertj:assertj-core:3.19.0"
}
@ParameterizedTest, @ValueSource
κ·ΈλΌ @ParameterizedTest μ΄λ Έν μ΄μ μ μΈμ μ¬μ©νλμ§ μ΄ν΄λ³΄κ² μ΅λλ€.
private Set<Integer> numbers;
@BeforeEach
void setUp() {
numbers = new HashSet<>();
numbers.add(1);
numbers.add(1);
numbers.add(2);
numbers.add(3);
}
@Test
void set_contains_test() {
assertThat(numbers.contains(1)).isTrue();
assertThat(numbers.contains(2)).isTrue();
assertThat(numbers.contains(3)).isTrue();
...
}
μ μ½λμ²λΌ Set 컬λ μ μ μ¬λ¬ κ°μ΄ νμΈλμ΄μλμ§ νμΈνλ €λ©΄ μ½λλ₯Ό μ¬λ¬λ² μμ±νλ μ€λ³΅ μ½λκ° λ°μνκ² λ©λλ€.
λ°λΌμ, μμ κ°μ΄ μ€λ³΅ μ½λκ° λ°μνμ λ @ParameterizedTest μ΄λ Έν μ΄μ μ μ¬μ©ν μ μλλ°μ,
μ μ½λλ₯Ό λ€μκ³Ό κ°μ΄ λνλΌ μ μμ΅λλ€.
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void set_contains_test(int element) {
assertThat(numbers.contains(element)).isTrue();
}
ν μ€νΈ κ²°κ³Όλ₯Ό μ΄ν΄λ³΄λ©΄ @ValueSource μ΄λ Έν μ΄μ μ μ μΈλ 1, 2, 3 μ κ°μ ν μ€νΈνλ κ²μ λ³Ό μ μμ΅λλ€.
@ValueSourceλ 리ν°λ΄ κ°μ λ°°μ΄μ λν μ κ·Όμ μ 곡νλ μ΄λ Έν μ΄μ μ λλ€.
μμΈν λ΄μ©μ 곡μλ¬Έμ μμ νμΈν΄μ£ΌμΈμ :)
@ValueSourceμ λ€λ₯Έ μμ λ‘ λ€μκ³Ό κ°μ΄ μ¬μ©ν μ μμ΅λλ€.
public class Numbers {
public static boolean isOdd(int number) {
return number % 2 != 0;
}
}
@ParameterizedTest
@ValueSource(ints = {1, 5, 9, -7, 15, 21}) // six numbers
void isOdd_ShouldReturnTrueForOddNumbers(int number) {
assertThat(Numbers.isOdd(number)).isTrue();
}
@ValueSourceμ μ½λλ λ€μκ³Ό κ°μ΅λλ€.
/*
* Copyright 2015-2020 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.params.provider;
import static org.apiguardian.api.API.Status.STABLE;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apiguardian.api.API;
/**
* {@code @ValueSource} is an {@link ArgumentsSource} which provides access to
* an array of literal values.
*
* <p>Supported types include {@link #shorts}, {@link #bytes}, {@link #ints},
* {@link #longs}, {@link #floats}, {@link #doubles}, {@link #chars},
* {@link #booleans}, {@link #strings}, and {@link #classes}. Note, however,
* that only one of the supported types may be specified per
* {@code @ValueSource} declaration.
*
* <p>The supplied literal values will be provided as arguments to the
* annotated {@code @ParameterizedTest} method.
*
* @since 5.0
* @see org.junit.jupiter.params.provider.ArgumentsSource
* @see org.junit.jupiter.params.ParameterizedTest
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.7")
@ArgumentsSource(ValueArgumentsProvider.class)
public @interface ValueSource {
/**
* The {@code short} values to use as sources of arguments; must not be empty.
*
* @since 5.1
*/
short[] shorts() default {};
/**
* The {@code byte} values to use as sources of arguments; must not be empty.
*
* @since 5.1
*/
byte[] bytes() default {};
/**
* The {@code int} values to use as sources of arguments; must not be empty.
*/
int[] ints() default {};
/**
* The {@code long} values to use as sources of arguments; must not be empty.
*/
long[] longs() default {};
/**
* The {@code float} values to use as sources of arguments; must not be empty.
*
* @since 5.1
*/
float[] floats() default {};
/**
* The {@code double} values to use as sources of arguments; must not be empty.
*/
double[] doubles() default {};
/**
* The {@code char} values to use as sources of arguments; must not be empty.
*
* @since 5.1
*/
char[] chars() default {};
/**
* The {@code boolean} values to use as sources of arguments; must not be empty.
*
* @since 5.5
*/
boolean[] booleans() default {};
/**
* The {@link String} values to use as sources of arguments; must not be empty.
*/
String[] strings() default {};
/**
* The {@link Class} values to use as sources of arguments; must not be empty.
*
* @since 5.1
*/
Class<?>[] classes() default {};
}
@ParameterizedTest, @CsvSource
μμ @ValueSource μ΄λ Έν μ΄μ μ μ¬μ©ν set ν μ€νΈμμ λͺ¨λ 쑰건μ νμ trueλ₯Ό 리ν΄νλλ‘ λμ΄μμλλ°μ,
λ§μ½ μμκ°μ μν©μ΄ μλ, μ λ ₯κ°μ λ°λΌ κ²°κ³Όκ°μ΄ λ€λ₯Έ κ²½μ°λ₯Ό ν μ€νΈ νλ €λ©΄ @CsvSourceλ₯Ό μ¬μ©ν΄ ν μ€νΈλ₯Ό ν μ μμ΅λλ€.
CSV(Comma Separated Values)λ μ΄λ¦μ ν΅ν΄ μ μ μλ―μ΄, μ½€λ§(default)λ₯Ό κΈ°μ€μΌλ‘ CSVλ₯Ό ꡬλΆν΄μ μ½μ΅λλ€.
⻠ꡬλΆμλ 컀μ€ν°λ§μ΄μ§μ΄ κ°λ₯ν©λλ€.
ν μ€νΈ μ½λλ λ€μκ³Ό κ°μ΅λλ€.
@DisplayName("true, false κ°μ κ°μ΄ 리ν΄νλ€")
@ParameterizedTest
@CsvSource(value = {"1:true", "2:true", "3:true", "4:false", "5:false"}, delimiter = ':')
void set_contains_true_false(int element, boolean expected) {
assertThat(numbers.contains(element)).isEqualTo(expected);
}
@CsvSource μ΄λ Έν μ΄μ μ delimiter μ μ§μ μ μν¨μΌλ‘μ¨ κ΅¬λΆμλ₯Ό μ§μ ν μ μμ΅λλ€.
μ μ½λμμ setμ 1, 2, 3 μ κ°μ§κ³ μκΈ° λλ¬Έμ trueλ₯Ό, 4μ 5λ falseλ₯Ό λ°νν©λλ€.
@ParameterizedTest, @MethodSource
@MethodSource μ΄λ Έν μ΄μ μ λ€μκ³Ό κ°μ μν©μμ μ¬μ©μ νμ΅λλ€.
μ«μμΌκ΅¬κ²μμ λν΄ μ§νλ‘κ·Έλλ°μ νλ λμ€, μ€νΈλΌμ΄ν¬ & λ³Όμ λν ν μ€νΈ μ½λλ₯Ό μμ±μ ν΄μΌνλλ°μ,
λ ν μ€νΈ λͺ¨λ νλ μ΄μ΄, μ»΄ν¨ν°μ μ«μλ₯Ό κ°μ§κ³ μμ΄μΌ ν©λλ€.
λ°λΌμ νλΌλ―Έν°λ₯Ό ν μ€νΈλ₯Ό νλλ° λ°λ‘ ꡬνμ νκ² λλ©΄ μ€λ³΅ μ½λκ° λ°μν΄μ @MethodSource μ΄λ Έν μ΄μ μ ν΅ν΄ μ¬λ¬ κ°λ€μ λν΄ λμΌνκ² μ¬μ©ν μ μλλ‘ μμ±μ νμ΅λλ€.
@MethodSource μ μ½λλ λ€μκ³Ό κ°μ΅λλ€.
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@API(status = STABLE, since = "5.7")
@ArgumentsSource(MethodArgumentsProvider.class)
public @interface MethodSource {
/**
* The names of factory methods within the test class or in external classes
* to use as sources for arguments.
*
* <p>Factory methods in external classes must be referenced by <em>fully
* qualified method name</em> — for example,
* {@code com.example.StringsProviders#blankStrings}.
*
* <p>If no factory method names are declared, a method within the test class
* that has the same name as the test method will be used as the factory
* method by default.
*
* <p>For further information, see the {@linkplain MethodSource class-level Javadoc}.
*/
String[] value() default "";
}
ν μ€νΈμ μ¬μ©ν μ€μ μ½λλ λ€μκ³Ό κ°μ΅λλ€.
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
...
@DisplayName("μ€νΈλΌμ΄ν¬ ν
μ€νΈ")
@ParameterizedTest
@MethodSource("generateData")
public void test1(List<Integer> playerLists, List<Integer> computerLists, int index) {
PlayResult playResult = new PlayResult();
int strikeCount = playResult.countStrike(playerLists, computerLists);
int[] result = {1, 0};
assertThat(strikeCount).isEqualTo(result[index]);
}
@DisplayName("λ³Ό ν
μ€νΈ")
@ParameterizedTest
@MethodSource("generateData")
void test_ball(List<Integer> playerLists, List<Integer> computerLists, int index) {
PlayResult playResult = new PlayResult();
int ballCount = playResult.countBall(playerLists, computerLists);
int[] result = {2, 0};
assertThat(ballCount).isEqualTo(result[index]);
}
static Stream<Arguments> generateData() {
return Stream.of(
Arguments.of(Arrays.asList(1, 2, 3), Arrays.asList(1, 3, 2), 0),
Arguments.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), 1)
);
}
generateData() λ©μλλ₯Ό ν΅ν΄ ν μ€νΈν νλΌλ―Έν°λ₯Ό Stream<Arguments>λ‘ μμ±ν©λλ€.
κ·Έ ν @MethodSource μ΄λ Έν μ΄μ μ κ΄νΈμ ν΄λΉ λ©μλ μ΄λ¦μ μμ±νλ©΄ νλΌλ―Έν° ν μ€νΈκ° κ°λ₯ν©λλ€.
@MethodSource μ΄λ
Έν
μ΄μ
μ΄ μλνλ ꡬ쑰λ₯Ό λλ΅μ μΌλ‘ λνλ΄λ©΄ μλμ κ°μ΅λλ€.
μ΄μμΌλ‘ JUnitμ νλΌλ―Έν° ν μ€νΈμ κ΄λ ¨λ @ParameterizedTest, @ValueSource, @CsvSource, @MethodSource μ΄λ Έν μ΄μ μ λν΄ κ°λ΅ν μ΄ν΄λ³΄μμ΅λλ€.
νΉμ μ μ΄λ Έν μ΄μ λ§κ³ λ AssertJμ λν΄ λ€μν ν μ€νΈ μ½λλ₯Ό μ΄ν΄λ³΄μλ €λ©΄ μλ λ§ν¬λ₯Ό μ°Έμ‘°ν΄μ£ΌμΈμ :)
https://www.baeldung.com/introduction-to-assertj
λ°°μ°λ©΄ λ°°μΈμλ‘ κ³΅λΆν κ² λ λ§μμ§λ κ² κ°μ΅λλ€ π
μμ κ°μ νλΌλ―Έν° ν μ€νΈλ λ€μν νλΌλ―Έν°λ₯Ό ν μ€νΈν΄μΌ νλ κ²½μ°, μ€λ³΅λλ μ½λλ₯Ό μ€μΌ μ μλ€λ μ μμ μ μ©ν λ°©λ²μΈ κ² κ°μ΅λλ€
References
https://www.baeldung.com/parameterized-tests-junit-5
'Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Spring AOP - (1) νλ‘μ ν¨ν΄, λ°μ½λ μ΄ν° ν¨ν΄ (0) | 2021.08.27 |
---|---|
Spring Boot Maven profile μ΄μ & κ°λ° DB λΆλ¦¬(AWS EC2) (6) | 2021.06.18 |
[Spring] κ°μ²΄λ³΅μ¬ BeanUtils.copyProperties() & μλ μ리 (0) | 2021.02.20 |
[Spring] Maven λ©ν°λͺ¨λ νλ‘μ νΈ (0) | 2021.02.09 |
[Spring] - @ModelAttribute, @RequestParam (0) | 2021.02.02 |
λκΈ