Статьи

Использование имени теста Junit

Назовите ваши тесты

Когда мы создаем тест Junit, обычно нет практического использования имени метода. Бегун Junit использует рефлексию для обнаружения методов тестирования, и начиная с версии 4 вы не можете больше запускать имя метода с test . Названия методов испытаний приведены для целей документации.

Есть разные стили, которым следуют люди. Вы можете назвать свой тест в given_Something_when_Something_then_Something стиле given_Something_when_Something_then_Something за given_Something_when_Something_then_Something я также следовал некоторое время. Другие школы начинают название метода с того, что мир should описать, что «должен» делать тестируемый объект. Я не очень понимаю, почему это значительно лучше, чем начинать название метода с test . Если все методы начинаются с одного и того же префикса, то это всего лишь шум. В наши дни я склонен называть методы простыми утверждениями о том, что делает SUT.

Как получить доступ к имени теста?

Технически вы можете называть свои методы, пока имена уникальны. Имя обычно не используется в тесте, и результат теста не должен зависеть от фактического названия метода теста. Несмотря на то, что Junit поддерживает способ доступа к имени метода.

Если у вас есть правило Junit

1
2
@Rule
public TestName name = new TestName();

вы можете обратиться к имени объекта в вашем тесте, получив имя фактического метода как

1
String testName = name.getMethodName();

Для чего мы можем использовать это?

Иногда тестируемый модуль создает огромную структуру, которую можно сериализовать в виде двоичного или текстового файла. Обычная практика – запускать тест один раз, проверять полученный файл и, если все в порядке, сохранить его для последующего сравнения. Последующие тестовые выполнения сравнивают фактический результат с тем, который был сохранен и проверен разработчиком.

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

В таких ситуациях имя теста можно использовать для создания имени файла, в котором хранятся данные теста. Название теста уникально и позволяет легко связать данные с тестом, который в этом нуждается. Я использовал этот подход в библиотеке jscglib . Эта библиотека предоставляет свободный API для создания исходного кода Java. Тесты содержат некоторый код директора шаблонов Java Builder, а затем полученный исходный код сохраняется в файл или сравнивается с уже сохраненным результатом.

Для сохранения файла был использован getTargetFileName метод getTargetFileName

1
2
3
4
5
private String getTargetFileName() {
        String testName = name.getMethodName();
        String fileName = "target/resources/" + testName + ".java";
        return fileName;
    }

Для получения имени ресурса был использован метод getResourceName :

1
2
3
4
private String getResourceName() {
        String testName = name.getMethodName();
        return testName + ".java";
    }

После этого загрузка и сохранение сгенерированного Java-кода были на одном дыхании:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
private void saveGeneratedProgram(String actual) throws IOException {
        File file = new File(getTargetFileName());
        file.getParentFile().mkdirs();
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buf = actual.getBytes("utf-8");
        fos.write(buf, 0, buf.length);
        fos.close();
    }
 
    private String loadJavaSource() {
        try {
            String fileName = getResourceName();
            InputStream is = this.getClass().getResourceAsStream(fileName);
            byte[] buf = new byte[3000];
            int len = is.read(buf);
            is.close();
            return new String(buf, 0, len, "utf-8");
        } catch (Exception ie) {
            return null;
        }
    }

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

Что вы не должны использовать имя для

На моем языке есть поговорка: «Все в чем-то хороши. По крайней мере, демонстрация неудачи. Следующий пример демонстрирует такой сбой.

Я видел код, который кодировал данные теста в название метода теста. Доступ к имени метода теста также был реализован странным образом. Программист, вероятно, не знал, что существует поддерживаемый способ получения имени метода. Это отсутствие знаний, возможно, остановило его или ее, чтобы сделать зло, но этот человек был гением. Тестовый тестовый метод вызывал статический метод вспомогательного класса. Этот статический метод вызывал исключение, он также перехватывал его и просматривал трассировку стека, чтобы определить имя метода вызывающего.

Получив доступ к имени, код применил регулярное выражение для извлечения значений из имени метода.

Резюме

Я не знаю, что намерение разработчиков Junit дало нам класс TestName . Вероятно, был какой-то вариант использования, который нуждался в функции. Я уверен, что они не предоставили функцию, потому что это было возможно сделать. Если вы не знаете, для чего хорош API, который вы предоставляете, вы, вероятно, не должны предоставлять его только потому, что можете. Начинающие программисты будут использовать это неправильно больше, чем хорошо.

С другой стороны, если вы видите в API что-то, что можно использовать, это не означает, что вы должны использовать эту функцию. Вы должны лучше понять цель функции, для которой она была разработана, и использовать ее соответствующим образом.

Написание модульных тестов важнее, чем их именование. Споры о наименовании модульных тестов бесполезны до тех пор, пока нет модульных тестов.

Пишите юнит-тесты столько, сколько нужно, но не больше.

Ссылка: Использование Junit Test Name от нашего партнера JCG Питера Верхаса в блоге Java Deep .