Каков наилучший способ чтения тестовых данных из файла CSV с помощью JUnit 5? - PullRequest
1 голос
/ 05 февраля 2020

Каков наилучший / рекомендуемый способ чтения тестовых данных из файла CSV с помощью JUnit 5?

Предполагается, что одна строка - это один тестовый случай, один столбец - один параметр, количество столбцов фиксировано, и разные столбцы могут иметь разные (basi c) типы: String, int, double.

Примером может быть:

public class Test{

    @Test
    // ready to use annotation that may load parameters from each line 
    public void shouldCalculateDiscount(String column1, long column2, double column3) {
        assertEquals(5, column1.length());
        assertEquals(column3, column2, 0.0001);
    }
}

Пример файла CSV:

column1,column2,column3
a,0,0.0
abcde,1,1.01
a-b-c,999,999.0

Подход, использующий аннотации, был бы идеальным, вероятно, чем-то аналогичным JUnit's @ ParameterizedTest.

Ответы [ 3 ]

3 голосов
/ 06 февраля 2020

Удивительно, но я нашел два хорошо документированных подхода, которые действительно отвечают на мой вопрос.

Первый один из книги Практическое модульное тестирование с JUnit и Mockito Томека Качановского , Он предлагает использовать следующее:

@RunWith(JUnitParamsRunner.class)
public class ReadCSVJunitParamsTest {

    @Test
    @FileParameters(value = "classpath:financial.csv", mapper = CsvWithHeaderMapper.class)
    public void testLetterCount(String value, long letterCount) {
        assertEquals(letterCount, LetterCounter.countLetters(value));
    }
}

Используется библиотека JUnitParams . Он может даже протестировать n-кратное декартово произведение значений параметров «, эффективно тестирующее каждую возможную комбинацию. » - см. Аннотацию @CombinedParameters.

Второй подход использует комбинацию @ CsvSource и @ParameterizedTest, прямо из .. JUnit 5.

public class ReadCSVJUnitParametrized {

    @ParameterizedTest
    @CsvFileSource(resources = "/financial.csv", numLinesToSkip = 1)
    public void testLetterCountParametrized(String value, long letterCount) {
        assertEquals(letterCount, LetterCounter.countLetters(value));
    }
}

Файл .csv , который я использовал для тестирования:

value,letterCount
,0
a,1
..aa,2
.!@#$%^&*(,0
0123456789,0
abcdefghij0,10 

LetterCounter класс:

public class LetterCounter {
    public static long countLetters(String value) {
        if (value == null) {
            return 0;
        }
        return value.chars().filter(Character::isLetter).count();
    }
}
1 голос
/ 05 февраля 2020

CSV обозначает значения, разделенные запятыми, так что по сути вы можете просто разделить, так как знаете используемый разделитель. Если вы пытаетесь использовать тестовые данные для нескольких тестов, вы можете попробовать:

List<String[]> columnValues = new ArrayList<String[]>();

@Before
public void init(){
    try {
        Scanner scanner = new Scanner(new File("myFile.csv"));
        while(scanner.hasNextLine()) {
            String[] values = scanner.nextLine().split(",");
            columnValues.add(values);
        }
    }catch(Exception e) {
        //whatever
    }
}

Затем в любом методе тестирования, который вы используете, вы можете просто разбить значения

@Test
public void myTest(){
    //set x to 1 to avoid columns
    for(int x = 1; x < columnValues.size(); x++) {
        String col1 = columnValues.get(x)[0];
        int col2 = Integer.parseInteger(columnValues.get(x)[1]);
        double col3 = Double.parseDouble(columnValues.get(x)[2]);
        double col4 = Double.parseDouble(columnValues.get(x)[3]);
        //test values here
    }
}

или, в качестве альтернативы, используйте заданные c индексы, если вы хотите проверить заданные c строки, или даже рандомизируйте их, если хотите, вместо того, чтобы тестировать все строки. Вы также могли, как вы упомянули, использовать эту концепцию аналогично в качестве параметров для тестов.

1 голос
/ 05 февраля 2020

Apache commons имеет хорошую библиотеку CSV, которую вы можете использовать. http://commons.apache.org/proper/commons-csv/user-guide.html

...