
Написание тестов JUnit в среде IDE NetBeans
В этом руководстве рассмотрены основы написания и выполнения модульных тестов JUnit в среде IDE NetBeans. Тестирование приложения является неотъемлемой частью цикла разработки, а написание и поддержка модульных тестов могут гарантировать корректную работу отдельных методов исходного кода. Интегрированная поддержка среды IDE для инфраструктуры модульного тестирования JUnit позволяет быстро и просто создавать тесты JUnit и наборы тестов.
В этом руководстве создаются простые модульные тесты JUnit 3 и JUnit 4 и наборы тестов для проекта библиотеки классов Java. Первая часть руководства посвящена созданию тестов в JUnit 3. Во второй части показан способ создания этих тестов в JUnit 4 с помощью аннотаций JUnit. Изучать обе части руководства не требуется, поскольку тесты совпадают, однако анализ способа написания тестов в обеих версиях позволяет выявить некоторые нововведения в JUnit 4.
Для получения дополнительных сведений относительно JUnit см. www.junit.org.
Содержание
Для работы с этим руководством требуется программное обеспечение и ресурсы, перечисленные ниже.
Создание проекта
Для работы с этим руководством требуется сначала создать проект библиотеки класса Java с именем JUnit-Sample.
Создание проекта библиотеки классов Java
- В главном меню выберите "File > New Project".
- Выберите библиотеку классов Java в категории Java и нажмите кнопку "Next".
- Введите JUnit-Sample в качестве имени проекта и укажите местоположение проекта.
- Снимите флажок "Use Dedicated Folder", если он установлен.
В рамках этого руководства копирование библиотек проекта в выделенную папку не целесообразно, поскольку совместное использование библиотек с другими пользователями или проектами не требуется. Эта возможность отсутствует в среде IDE NetBeans 6.0.
Нажмите кнопку "Next".
- Нажмите кнопку "Finish".
После создания проекта в узле "Test Libraries" в окне "Projects" можно увидеть, что проект содержит библиотеки JUnit 3 и JUnit 4. В среде IDE обе библиотеки добавляются к новым проектам по умолчанию. При первом создании теста JUnit в среде IDE запрашивается выбор версии и удаляется лишняя библиотека.
Создание классов Java
В этом упражнении будет загружен пример проекта решения, и в созданный проект библиотеки классов будут скопированы файлы Utils.java и Vectors.java.
- Щелкните правой кнопкой мыши узел "Source Packages" в окне "Projects" и выберите в появившемся меню "New > Java Package".
- Введите sample в качестве имени пакета. Нажмите кнопку "Finish".
- Загрузите и распакуйте архив проекта JUnitSampleSol, после чего откройте проект в среде IDE.
- Скопируйте файлы Utils.java и Vectors.java в папку "Source Packages" проекта JUnitSampleSol в sample в папку "Source Packages" проекта JUnit-Sample.
Анализ исходного кода для классов показывает, что класс Utils.java включает три метода (computeFactorial, concatWords и normalizeWord), а Vectors.java – два метода (equals и scalarMultiplication). На следующем шаге будут созданы тестовые классы для каждого класса и написаны тестовые примеры для методов.
Написание модульных тестов JUnit 3
В этой части руководства рассматривается создание основных модульных тестов JUnit 3 для классов Vectors.java и Utils.java. Для создания скелетных тестовых классов, основанных на классах проекта, будет использована среда IDE. Затем созданные тестовые методы будут изменены, а также добавлены новые тестовые методы.
При первом использовании среды IDE для создания тестов для проекта будет выведен запрос на выбор версии JUnit. Выбранная версия определяется как версия JUnit по умолчанию, и все последующие тесты и наборы тестов в среде IDE будут создаваться для этой версии.
Создание тестового класса для Vectors.java
В этом упражнении будет создан скелет теста JUnit для Vectors.java.
- Щелкните правой кнопкой мыши Vectors.java и выберите "Tools > Create JUnit Tests".
- В диалоговом окне "Select JUnit Version" выберите JUnit 3.x.
В результате выбора JUnit 3.x в среде IDE из проекта удаляется библиотека JUnit 4.
- Измените имя тестового класса на VectorsJUnit3Test в диалоговом окне "Create Tests".
В результате изменения имени тестового класса появится предупреждение об изменении имени. Имя по умолчанию – это имя тестируемого класса с добавленным словом "Test". Например, для класса MyClass.java именем тестового класса по умолчанию будет MyClassTest.java. Рекомендуется сохранить имя по умолчанию, но в рамках данного руководства имя будет изменено, так как в этом же пакете будут созданы тесты JUnit 4, а имена тестовых классов должны быть различными.
- Снимите флажки "Test Initializer" и "Test Finalizer". Нажмите кнопку "OK".
При нажатии кнопки "OK" в среде IDE создается скелет теста JUnit в каталоге пакета тестов sample.
Для создания тестов в пакетах тестов необходимо указать каталог. Местоположение по умолчанию для каталога пакетов тестов находится на корневом уровне проекта, но в зависимости от типа проекта можно указать другое местоположение для каталога в диалоговом окне свойств проекта "Properties".
Анализ созданного тестового класса VectorsJUnit3Test.java в редакторе показывает, что в среде IDE был создан следующий тестовый класс с тестовыми методами для методов equal и scalarMultiplication.
public class VectorsJUnit3Test extends TestCase {
/**
* Test of equal method, of class Vectors.
*/
public void testEqual() {
System.out.println("equal");
int[] a = null;
int[] b = null;
boolean expResult = false;
boolean result = Vectors.equal(a, b);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
/**
* Test of scalarMultiplication method, of class Vectors.
*/
public void testScalarMultiplication() {
System.out.println("scalarMultiplication");
int[] a = null;
int[] b = null;
int expResult = 0;
int result = Vectors.scalarMultiplication(a, b);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
}
Тело метода каждого созданного теста приводится исключительно в учебных целях и для рассматриваемого теста должно быть изменено. Если автоматическое создание кода не требуется, можно снять флажок "Default Method Bodies" в диалоговом окне "Create Tests".
При создании средой IDE имен для тестовых методов каждому имени метода предшествует слово test, так как в JUnit 3 для определения тестов используются правила именования и отражения. Для определения тестовых методов имя тестового метода должно соответствовать синтаксису test<NAME>.
В JUnit 4 не требуется использовать этот синтаксис для имен тестовых методов, так как для идентификации тестовых методов можно применять аннотации, а тестовый класс больше не используется для расширения TestCase.
Написание тестовых методов для Vectors.java
В этом упражнении созданные тестовые методы будут изменены для обеспечения их функционирования, а также будут изменены выходные сообщения по умолчанию. Изменять выходные сообщения для выполнения тестов не требуется, но может потребоваться их изменение для идентификации результатов, отображаемых в окне вывода "JUnit Test Results".
- Откройте файл VectorsJUnit3Test.java в редакторе.
- Измените скелет теста для testScalarMultiplication путем изменения значения println и удаления созданных переменных. После этого тестовый метод должен выглядеть следующим образом (изменения выделены полужирным шрифтом):
public void testScalarMultiplication() {
System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");
assertEquals(expResult, result);
}
- Затем добавьте несколько подтверждений для тестирования метода.
public void testScalarMultiplication() {
System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");
assertEquals( 0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));
assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));
assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));
assertEquals( 0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));
assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));
}
В этом тестовом методе используется метод JUnit assertEquals. Для использования утверждения необходимо указать входные переменные и ожидаемый результат. Для успешного прохождения теста метод теста должен выдать все ожидаемые результаты на основе переменных, введенных при выполнении тестового метода. Для охвата возможных перестановок следует добавить достаточное количество утверждений.
- Измените скелет теста для testEqual путем удаления созданных тел методов и добавления следующего println.
System.out.println("* VectorsJUnit3Test: testEqual()");
Тестовый метод в результате должен выглядеть следующим образом:
public void testEqual() {
System.out.println("* VectorsJUnit3Test: testEqual()");
}
- Измените метод testEqual путем добавления следующих утверждений (выделены полужирным шрифтом).
public void testEqual() {
System.out.println("* VectorsJUnit3Test: testEqual()");
assertTrue(Vectors.equal(new int[] {}, new int[] {}));
assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));
assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));
assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));
assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));
assertFalse(Vectors.equal(new int[] {}, new int[] {0}));
assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));
assertFalse(Vectors.equal(new int[] {0}, new int[] {}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));
}
В этом тесте используются методы JUnit assertTrue и assertFalse для тестирования всех возможных результатов. Для успешного прохождения теста этим методом утверждения assertTrue должны быть истинными, а assertFalse – ложными.
Сравните: Написание тестовых методов для Vectors.java (JUnit 4)
Создание тестового класса для Utils.java
Теперь следует создать скелеты тестов для Utils.java. При создании теста в предыдущем упражнении в среде IDE запрашивалась версия JUnit. В этом случае запрос выбора версии не выводится.
- Щелкните правой кнопкой мыши Utils.java и выберите "Tools > Create JUnit Tests".
- Установите в диалоговом окне флажки "Test Initializer" и "Test Finalizer", если они еще не установлены.
- Измените имя тестового класса на UtilsJUnit3Test в диалоговом окне "Create Tests". Нажмите кнопку "OK".
При нажатии кнопки "OK" в среде IDE создается файл теста UtilsJUnit3Test.java в каталоге "Test Packages > samples". Обратите внимание на то, что помимо создания скелетов тестов testComputeFactorial, testConcatWords и testNormalizeWord для методов в Utils.java в среде IDE также создаются методы инициализатора теста setUp и финализатора теста tearDown.
Написание методов теста для Utils.java
В этом упражнении будет добавлено несколько тестов, демонстрирующих общие принципы работы тестов JUnit. К методам также будет добавлен println, так как некоторые из методов не выводят данные по умолчанию. В результате добавления к методам println можно просмотреть окно результата тестирования JUnit для проверки выполнения методов и порядка их запуска.
Инициализаторы и финализаторы тестов
Методы setUp и tearDown используются для инициализации и финализации условий теста. Для тестирования Utils.java методы setUp и tearDown не требуются, они представлены здесь для демонстрации принципов их работы.
Метод setUp является методом инициализации теста и выполняется перед каждым тестом в классе теста. Для выполнения тестов метод инициализации теста не требуется, однако его следует использовать при необходимости инициализации некоторых переменных до выполнения теста.
Метод tearDown является методом финализатора теста и выполняется после каждого тестового примера в тестовом классе. Метод финализатора теста не требуется для выполнения тестов, однако он может использоваться для удаления всех данных, задействованных при выполнении тестов.
- Внесите следующие изменения (выделены полужирным шрифтом) в код println каждого метода.
@Override
protected void setUp() throws Exception {
super.setUp();
System.out.println("* UtilsJUnit3Test: setUp() method");
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
System.out.println("* UtilsJUnit3Test: tearDown() method");
}
При выполнении теста для каждого метода в окне вывода "Test Results" отображается текст println. Если код println не добавлен, окно результата выполнения методов не появится.
Тестирование с помощью простого утверждения
Этот простой тест предназначен для тестирования метода concatWords. Вместо использования созданного метода теста testConcatWords будет добавлен новый метод теста с именем testHelloWorld, использующий единственное простое утверждение для проверки правильности сцепления строк методом. Для подтверждения assertEquals в тесте используется синтаксис assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) для проверки соответствия фактического результата ожидаемому результату. Если входные данные для метода concatWords – "Hello", ", ", "world" и "!", то ожидаемый результат должен быть равен "Hello, world!".
- Удалите созданный тестовый метод testConcatWords.
- Добавьте следующий метод для тестирования метода concatWords.
public void testHelloWorld() {
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
}
- Добавьте оператор println для вывода на экран текста о тесте в окне "JUnit Test Results".
public void testHelloWorld() {
System.out.println("* UtilsJUnit3Test: test method 1 - testHelloWorld()");
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
Сравните: Тестирование с помощью простого утверждения (JUnit 4)
Тестирование с использованием тайм-аута
Этот тест демонстрирует проверку метода на длительность выполнения. Если метод выполняется слишком долго, поток выполнения теста прерывается, а тест завершается сбоем. Можно указать предел времени для теста.
Тестовый метод вызывает метод computeFactorial в Utils.java. Можно предположить, что метод computeFactorial правилен, но в этом случае требуется его протестировать на выполнение вычисления за 1000 миллисекунд. Поток выполнения computeFactorial и поток выполнения теста запускаются одновременно. Поток выполнения теста останавливается через 1000 миллисекунд и выдает TimeoutException, если поток выполнения computeFactorial не завершается раньше. Потребуется добавить сообщение для его отображения при выдаче TimeoutException.
- Удалите созданный тестовый метод testComputeFactorial.
- Добавьте метод testWithTimeout, вычисляющий факториал случайного числа.
public void testWithTimeout() throws InterruptedException, TimeoutException {
final int factorialOf = 1 + (int) (30000 * Math.random());
System.out.println("computing " + factorialOf + '!');
Thread testThread = new Thread() {
public void run() {
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
};
}
- Исправьте операторы импорта для импорта java.util.concurrent.TimeoutException.
- Добавьте к методу следующий код (выделен полужирным шрифтом) для прерывания потока выполнения и вывода на экран сообщения в случае слишком долгого выполнения теста.
Thread testThread = new Thread() {
public void run() {
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
};
testThread.start();
Thread.sleep(1000);
testThread.interrupt();
if (testThread.isInterrupted()) {
throw new TimeoutException("the test took too long to complete");
}
}
Можно изменить строку Thread.sleep для изменения количества миллисекунд до выдачи тайм-аута.
- Добавьте следующий код println (выделен полужирным шрифтом) для отображения текста теста в окне "JUnit Test Results".
public void testWithTimeout() throws InterruptedException, TimeoutException {
System.out.println("* UtilsJUnit3Test: test method 2 - testWithTimeout()");
final int factorialOf = 1 + (int) (30000 * Math.random());
System.out.println("computing " + factorialOf + '!');
Сравните: Тестирование с использованием тайм-аута (JUnit 4)
Тестирование на ожидаемое исключение
Этот тест предназначен для тестирования на ожидаемое исключение. Метод завершится сбоем, если не будет выдано ожидаемое исключение. В этом случае выполняется тестирование метода computeFactorial на результат IllegalArgumentException с отрицательной входной переменной (-5).
- Добавьте следующий метод testExpectedException для вызова метода computeFactorial с входной переменной -5.
public void testExpectedException() {
try {
final int factorialOf = -5;
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
fail("IllegalArgumentException was expected");
} catch (IllegalArgumentException ex) {
}
}
- Добавьте следующий код println (выделен полужирным шрифтом) для отображения текста о тесте в окне "JUnit Test Results".
public void testExpectedException() {
System.out.println("* UtilsJUnit3Test: test method 3 - testExpectedException()");
try {
Сравните: Тестирование на ожидаемое исключение (JUnit 4)
Отключение теста
Этот тест включает способы временного отключения тестового метода. В JUnit 3 в качестве тестовых методов распознаются только методы с именем, начинающимся с test. В этом случае для отключения метода требуется ввести перед именем DISABLED.
- Удалите созданный тестовый метод testNormalizeWord.
- Добавьте следующий тестовый метод к тестовму классу.
public void testTemporarilyDisabled() throws Exception {
System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");
assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
При выполнении тестового класса будет выполнен тестовый метод testTemporarilyDisabled.
- Введите DISABLED_ (выделено полужирным шрифтом) перед именем тестового метода.
public void DISABLED_testTemporarilyDisabled() throws Exception {
System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");
assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
Сравните: Отключение теста (JUnit 4)
После написания всех тестов можно выполнить тест и просмотреть результат в окне "JUnit Test Results".
Выполнение тестов
При выполнении теста JUnit результаты отображаются в окне "JUnit Test Results" в среде IDE. Можно выполнить отдельные тестовые классы JUnit либо выбрать в главном меню "Run > Test ИМЯ_ПРОЕКТА" для выполнения всех тестов проекта. При выборе "Run > Test" в среде IDE выполняются все тестовые классы в папке "Test Packages". Для выполнения отдельного тестового класса щелкните правой кнопкой мыши тестовый класс в узле "Test Packages" и выберите "Run File".
- В главном меню выберите "Run > Test JUnit-Sample".
При выполнении теста будет получен один из следующих результатов в окне "JUnit Test Results".
В примере на этом рисунке (для увеличения щелкните изображение) проект успешно прошел все тесты. На левой панели выводятся результаты отдельных тестовых методов, а на правой панели выводится результат теста. В окне вывода отображается порядок выполнения тестов. Добавление к каждому тестовому методу println обеспечивает вывод имени теста в окне вывода. Можно также отметить, что в UtilJUnit3Test метод setUp выполнялся перед каждым тестовым методу, а метод tearDown выполнялся после каждого метода.
В примере на этом рисунке (для увеличения щелкните изображение) тестирование проекта завершилось сбоем. Выполнение метода testTimeout заняло слишком много времени, поэтому поток выполнения теста был прерван и явился причиной сбоя теста. Для вычисления факториала случайного числа потребовалось более 1000 миллисекунд (22 991).
Следующее действие после создания классов модульного теста заключается в создании наборов тестов. Описание способа запуска указанных тестов группой вместо выполнения каждого теста по отдельности приводится в разделе Создание наборов тестов "JUnit 3".
Написание тестов JUnit 4
В этом упражнении будут созданы модульные тесты JUnit 4 для классов Vectors.java и Utils.java. Тесты JUnit 4 аналогичны тестам JUnit 3, однако при написании этих тестов применяется более простой синтаксис.
В проекте будут использованы созданные в среде IDE скелеты тестов, основанные на классах. При первом использовании среды IDE для создания некоторых скелетов тестов будет выведен запрос на выбор версии JUnit.
Если в качестве версии по умолчанию для тестов уже выбрана версия JUnit 3.x, то эту версию следует изменить на JUnit 4.x. Для изменения версии JUnit по умолчанию щелкните правой кнопкой мыши узел "Test Libraries", выберите "Add Library" и добавьте к проекту библиотеки JUnit 4. В случае создания нового теста при появлении запроса на выбор версии JUnit выберите версию 4.x. При выборе JUnit 4.x в среде IDE будут удалены лишние библиотеки JUnit 3.x. Тесты JUnit 3 также можно будет выполнять, но для новых тестов будет использоваться JUnit 4.
Создание тестового класса для Vectors.java
В этом упражнении будут созданы скелеты теста JUnit для Vectors.java.
- Щелкните правой кнопкой мыши Vectors.java и выберите "Tools > Create JUnit Tests".
- В диалоговом окне "Select JUnit Version" выберите JUnit 4.x.
При выборе JUnit 4.x в среде IDE удаляются библиотеки JUnit 3. Если в проект добавлены библиотеки JUnit 4, можно писать и выполнять тесты JUnit 3 и JUnit 4.
- В диалоговом окне "Create Tests" измените имя тестового класса на VectorsJUnit4Test.
В результате изменения имени тестового класса появится предупреждение об изменении имени. Имя по умолчанию – это имя тестируемого класса с добавленным словом "Test". Например, для класса MyClass.java именем по умолчанию тестового класса будет MyClassTest.java. В отличие от JUnit 3, в JUnit 4 добавление слова "Test" к имени теста не обязательно. Рекомендуется сохранить имя по умолчанию, но так как в рамках данного руководства все тесты JUnit создаются в одном пакете, имена тестовых классов должны быть различны.
- Снимите флажки "Test Initializer" и "Test Finalizer". Нажмите кнопку "OK".
При нажатии кнопки "OK" в среде IDE создается скелет теста JUnit в каталоге пакета тестов sample.
Для создания тестов в пакетах тестов необходимо указать каталог. Местоположение по умолчанию для каталога пакетов тестов находится на корневом уровне проекта, но можно указать другое местоположение для каталога в диалоговом окне свойств проекта "Properties".
При просмотре в редакторе VectorsJUnit3Test.java можно отметить, что в среде IDE созданы тестовые методы testEqual и testScalarMultiplication. В JUnit 4 каждый тестовый метод имеет аннотацию @Test. В среде IDE имена для тестовых методов создаются на основе имен метода в Vectors.java, но к имени тестового метода не обязательно добавлять test. Тело по умолчанию каждого созданного тестового метода представлено исключительно в учебных целях и для фактического использования должно быть изменено.
Если автоматическое создание тел методов не требуется, можно снять флажок "Default Method Bodies" в диалоговом окне "Create Tests".
В среде IDE также создаются следующие методы инициализатора и финализатора классов теста:
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
В среде IDE методы инициализатора и финализатора классов создаются по умолчанию при создании класса теста JUnit 4. Аннотации @BeforeClass и @AfterClass используются для выбора методов, которые должны быть запущены до и после выполнения тестового класса. Методы можно удалить, так как для тестирования Vectors.java они не нужны.
Также можно выполнить настройку методов, созданных по умолчанию при настройке свойств JUnit в окне "Options".
Написание тестовых методов для Vectors.java
В этом упражнении будет изменен каждый из автоматически созданных тестовых методов для тестирования методов при помощи метода JUnit assert и изменения имен тестовых методов. JUnit 4 предоставляет дополнительную гибкость при именовании тестовых методов, поскольку они определяются аннотацией @Test и не требуют добавления слова test к имени.
- Откройте в редакторе VectorsJUnit4Test.java.
- Измените тестовый метод для testScalarMultiplication путем изменения имени метода, значения println и удаления созданных переменных. После этого тестовый метод должен выглядеть следующим образом (изменения выделены полужирным шрифтом):
@Test
public void ScalarMultiplicationCheck() {
System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");
assertEquals(expResult, result);
}
При написании тестов изменять результат вывода не требуется. В этом упражнении это выполнено для упрощения идентификации результатов тестирования в окне вывода.
- Затем добавьте несколько подтверждений для тестирования метода.
@Test
public void ScalarMultiplicationCheck() {
System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");
assertEquals( 0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));
assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));
assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));
assertEquals( 0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));
assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));
}
В этом тестовом методе используется метод JUnit assertEquals. Для использования утверждения необходимо указать входные переменные и ожидаемый результат. Для успешного прохождения теста тестовый метод должен выдать все ожидаемые результаты на основе переменных, введенных при выполнении тестового метода. Также необходимо добавить достаточное количество утверждений для охвата возможных перестановок.
- Измените имя тестового метода с testEqual на equalsCheck.
- Измените тестовый метод equalsCheck путем удаления созданного тела метода и добавлением следующего оператора println.
System.out.println("* VectorsJUnit4Test: equalsCheck()");
Тестовый метод в результате должен выглядеть следующим образом:
@Test
public void equalsCheck() {
System.out.println("* VectorsJUnit4Test: equalsCheck()");
}
- Измените метод equalsCheck путем добавления следующих утверждений (выделены полужирным шрифтом).
@Test
public void equalsCheck() {
System.out.println("* VectorsJUnit4Test: equalsCheck()");
assertTrue(Vectors.equal(new int[] {}, new int[] {}));
assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));
assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));
assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));
assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));
assertFalse(Vectors.equal(new int[] {}, new int[] {0}));
assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));
assertFalse(Vectors.equal(new int[] {0}, new int[] {}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));
assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));
}
В этом тесте используются методы JUnit assertTrue и assertFalse для проверки всех возможных результатов. Для успешного прохождения теста утверждения assertTrue должны быть истинными, а assertFalse – ложными.
Сравните: Написание тестовых методов для Vectors.java (JUnit 3)
Создание тестового класса для Utils.java
Теперь перейдем к созданию тестовых методов JUnit для Utils.java. При создании тестового класса в предыдущем упражнении в среде IDE выводился запрос на выбор версии JUnit. В этот раз выбирать версию не потребуется, так как версия JUnit уже определена, и все последующие тесты JUnit будут созданы с использованием этой версии.
Если выбрана версия JUnit 4, написание и выполнение тестов JUnit 3 также допустимо, но в среде IDE для создания скелетов теста используется шаблон JUnit 4.
- Щелкните правой кнопкой мыши Utils.java и выберите "Tools > Create JUnit Tests".
- Устновите в диалоговом окне флажки "Test Initializer" и "Test Finalizer", если они еще не установлены.
- В диалоговом окне "Create Tests" измените имя тестового класса на UtilsJUnit4Test. Нажмите кнопку "OK".
При нажатии кнопки "OK" в среде IDE создается файл теста UtilsJUnit4Test.java в каталоге "Test Packages > samples". При этом в среде IDE будут созданы тестовые методы testComputeFactorial, testConcatWords и testNormalizeWord для методов в Utils.java. В среде IDE также создаются методы инициализатора и финализатора для теста и тестового класса.
Написание тестовых методов для Utils.java
В этом упражнении будет добавлено несколько тестов, демонстрирующих общие элементы теста JUnit. Также необходимо добавить в методы println, так как выполнение некоторых методов не приводит к отображению в окне "JUnit Test Results" информации, указывающей на выполнение или успешное прохождение теста. Добавление println в методы позволит отслеживать процесс выполнения методов и порядок их выполнения.
Инициализаторы и финализаторы тестов
При создании тестового класса для Utils.java в среде IDE создаются аннотированные методы инициализатора и финализатора. В качестве имени метода можно выбрать любое имя, так как обязательных требований в отношении имен не существует.
Для тестирования Utils.java не требуются методы инициализатора и финализатора, но они рассматриваются в этом руководстве для демонстрации принципов их работы.
В JUnit 4 для обозначения следующих типов методов инициализатора и финализатора можно использовать аннотации.
- Инициализатор тестового класса. Метод маркируется как метод инициализации тестового класса аннотацией @BeforeClass. Метод инициализации тестового класса запускается только один раз и выполняется только перед выполнением любых других методов в тестовом классе. Например, вместо создания подключения к базе данных в инициализаторе теста и создания нового подключения перед каждым тестовым методом можно использовать инициализатор тестового класса для открытия подключения перед выполнением тестов. Затем можно закрыть подключение в финализаторе тестового класса.
- Финализатор тестового класса. Метод маркируется как метод финализатора тестового класса аннотацией @AfterClass. Метод финализатора тестового класса выполняется только один раз и только после выполнения других методов в тестовом классе.
- Инициализатор теста. Метод маркируется как метод инициализации теста аннотацией @Before. Метод инициализации теста выполняется перед каждым тестом в тестовом классе. Для выполнения тестов метод инициализации теста не требуется, однако его следует использовать при необходимости инициализации некоторых переменных до выполнения теста.
- Финализатор теста. Метод маркируется как метод финализатора теста аннотацией @After. Метод финализатора теста выполняется после каждого теста в тестовом классе. Метод финализатора теста не требуется для выполнения тестов, но финализатор может использоваться для удаления всех данных, задействованных при выполнении тестов.
Для добавления println внесите следующие изменения (выделены полужирным шрифтом) в методы инициализатора и финализатора.
@BeforeClass
public static void setUpClass() throws Exception {
System.out.println("* UtilsJUnit4Test: @BeforeClass method");
}
@AfterClass
public static void tearDownClass() throws Exception {
System.out.println("* UtilsJUnit4Test: @AfterClass method");
}
@Before
public void setUp() {
System.out.println("* UtilsJUnit4Test: @Before method");
}
@After
public void tearDown() {
System.out.println("* UtilsJUnit4Test: @After method");
}
Сравните: Инициализаторы и финализаторы тестов (JUnit 3)
При выполнении тестового класса добавленный ранее текст println отображается в окне вывода "JUnit Test Results". Таким образом, информация, указывающая на выполнение методов инициализатора и финализатора, выводится только в том случае, если был добавлен println.
Тестирование с помощью простого подтверждения
Этот простой тест предназначен для тестирования метода concatWords. Вместо использования созданного тестового метода testConcatWords будет добавлен новый тестовый метод с именем helloWorldCheck, использующий единственное простое утверждение для проверки правильности сцепления строк методом. Для утверждения assertEquals в тесте используется синтаксис assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) для проверки соответствия фактического результата ожидаемому результату. Если входные данные для метода concatWords – "Hello", ",", "world" и "!", то ожидаемый результат должен быть равен "Hello, world!".
- Удалите созданный тестовый метод testConcatWords.
- Добавьте следующий метод helloWorldCheck для тестирования Utils.concatWords.
@Test
public void helloWorldCheck() {
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
}
- Добавьте оператор println для вывода на экран текста о тесте в окне "JUnit Test Results".
@Test
public void helloWorldCheck() {
System.out.println("* UtilsJUnit4Test: test method 1 - helloWorldCheck()");
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
Сравните: Тестирование с помощью простого утверждения (JUnit 3)
Тестирование с использованием тайм-аута
Этот тест демонстрирует проверку метода на длительность выполнения. Если метод выполняется слишком долго, поток выполнения теста прерывается, а тест завершается сбоем. Можно указать предел времени для теста.
Тестовый метод вызывает метод computeFactorial в Utils.java. Можно предположить, что метод computeFactorial правилен, но в этом случае требуется его протестировать на выполнение вычисления за 1000 миллисекунд. Это выполняется путем прерывания потока выполнения теста через 1000 миллисекунд. При прерывании потока выполнения тестовый метод выдает TimeoutException.
- Удалите созданный тестовый метод testComputeFactorial.
- Добавьте метод testWithTimeout, вычисляющий факториал случайного числа.
@Test
public void testWithTimeout() {
final int factorialOf = 1 + (int) (30000 * Math.random());
System.out.println("computing " + factorialOf + '!');
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
- Добавьте следующий код (выделен полужирным шрифтом) для определения тайм-аута и прерывания потока выполнения в случае слишком долгого выполнения метода.
@Test(timeout=1000)
public void testWithTimeout() {
final int factorialOf = 1 + (int) (30000 * Math.random());
Как видно в примере, для тайм-аута установлено значение 1000 миллисекунд.
- Добавьте следующий код println (выделен полужирным шрифтом) для отображения текста о тесте в окне "JUnit Test Results".
@Test(timeout=1000)
public void testWithTimeout() {
System.out.println("* UtilsJUnit4Test: test method 2 - testWithTimeout()");
final int factorialOf = 1 + (int) (30000 * Math.random());
System.out.println("computing " + factorialOf + '!');
Сравните: Тестирование с использованием тайм-аута (JUnit 3)
Тестирование на ожидаемое исключение
Этот тест предназначен для тестирования на ожидаемое исключение. Метод завершится сбоем, если не будет выдано ожидаемое исключение. В этом случае выполняется тестирование метода computeFactorial на результат IllegalArgumentException с отрицательной входной переменной (-5).
- Добавьте следующий метод testExpectedException для вызова метода computeFactorial со входной переменной -5.
@Test
public void checkExpectedException() {
final int factorialOf = -5;
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
- Добавьте следующее свойство (выделено полужирным шрифтом) в аннотацию @Test для определения необходимости выдачи IllegalArgumentException в результате выполнения теста.
@Test(expected=IllegalArgumentException.class)
public void checkExpectedException() {
final int factorialOf = -5;
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
- Добавьте следующий код println (выделен полужирным шрифтом) для отображения текста о тесте в окне "JUnit Test Results".
@Test (expected=IllegalArgumentException.class)
public void checkExpectedException() {
System.out.println("* UtilsJUnit4Test: test method 3 - checkExpectedException()");
final int factorialOf = -5;
System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
Сравните: Тестирование на ожидаемое исключение (JUnit 3)
Отключение теста
Этот тест включает способы временного отключения тестового метода. Для отключения теста в JUnit 4 следует добавить аннотацию @Ignore.
- Удалите созданный тестовый метод testNormalizeWord.
- Добавьте следующий тестовый метод к тестовому классу.
@Test
public void temporarilyDisabledTest() throws Exception {
System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");
assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
При выполнении тестового класса будет выполнен тестовый метод temporarilyDisabledTest.
- Для отключения теста добавьте аннотацию @Ignore (выделена полужирным шрифтом) над @Test.
@Ignore
@Test
public void temporarilyDisabledTest() throws Exception {
System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");
assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
- Исправьте операторы импорта для импорта org.junit.Ignore.
Сравните: Отключение теста (JUnit 3)
Теперь после написания всех тестов можно выполнить тест и просмотреть результат в окне "JUnit Test Results".
Выполнение тестов
В среде IDE можно выполнять тесты JUnit для всего приложения или для отдельных файлов и просматривать результаты. Самым простым способом выполнения всех модульных тестов для проекта является выбор в главном меню "Run > Test <ИМЯ_ПРОЕКТА>". При выборе этого метода в среде IDE запускаются все тестовые классы в папке с тестами. Для выполнения отдельного тестового класса щелкните правой кнопкой мыши тестовый класс в узле "Test Packages" и выберите "Run File".
- Щелкните правой кнопкой мыши UtilsJUnit4Test.java в окне "Projects".
- Выберите "Run File".
При запуске UtilsJUnit4Test.java в среде IDE выполняются только тесты в тестовом классе. На следующем рисунке представлен пример окна "JUnit Test Results" в случае успешного прохождения классом всех тестов.
В примере на рисунке (для увеличения щелкните изображение) в среде IDE был выполнен тест JUnit для Utils.java, при этом класс успешно прошел все тесты. На левой панели выводятся результаты отдельных тестовых методов, а на правой панели выводится результат теста. В окне вывода отображается порядок выполнения тестов. Добавление к каждому тестовому методу оператора println обеспечивает вывод имени теста в окне вывода. В рассматриваемом примере в тесте UtilsJUnit4Test метод инициализатора тестового класса с аннотацией @BeforeClass был выполнен до выполнения всех других методов и только один раз. Метод финализатора тестового класса с аннотацией @AfterClass был выполнен последним, после выполнения всех остальных методов в классе. Метод инициализатора теста с аннотацией @Before выполнялся до выполнения каждого тестового метода.
Следующий шаг после создания классов модульного теста заключается в создании наборов тестов. Описание способа запуска указанных тестов группой вместо выполнения каждого теста по отдельности приводится в разделе Создание наборов тестов "JUnit 4".
Создание наборов тестов
При создании тестов для проекта обычно необходимо создать большое количество тестовых классов. При выполнении тестовых классов по отдельности или запуске всех тестов проекта во многих случаях требуется выполнить определенное количество тестов или тесты в определенном порядке. Это можно осуществить путем создания одного или более набора тестов. Например, можно создать наборы тестов для тестирования определенных аспектов кода или конкретных условий.
Набор тестов, по сути, является классом, в который включен метод для вызова указанных тестов, например, определенных тестовых классов, тестовых методов в тестовых классах и других наборов тестов. Набор тестов может быть включен в тестовый класс, однако для набора тестов рекомендуется создать отдельные классы.
Наборы тестов JUnit 3 и JUnit 4 можно создать для проекта вручную или с использованием возможностей среды IDE. При использовании среды IDE для создания набора тестов по умолчанию в среде IDE генерируется код, вызывающий все тестовые классы в той же папке, где находится набор тестов. После создания набора тестов можно изменить класс для определения тестов, которые требуется выполнить в составе этого набора.
Создание набора тестов JUnit 3
При выборе JUnit 3 в качестве версии тестов в среде IDE могут быть созданы наборы тестов JUnit 3 на основе тестовых классов в папке с тестами. В JUnit 3 необходимо определить тестовые классы, которые должны быть включены в набор тестов, путем создания экземпляра TestSuite и использования метода addTest для каждого теста.
- Щелкните правой кнопкой мыши узел проекта в окне "Projects" и выберите "New > Other" для открытия мастера создания файла.
- Выберите категорию JUnit и "Test Suite". Нажмите кнопку "Next".
- Введите имя файла JUnit3TestSuite.
- Выберите папку sample для создания набора тестов в типовой папке в папке с тестами.
- Снимите флажки "Test Initializer" и "Test Finalizer". Нажмите кнопку "Finish".
При нажатии кнопки "Finish" в среде IDE создается класс набора тестов в папке sample, который затем открывается в редакторе. Если папка sample содержит тестовые классы VectorsJUnit3Test.java и UtilsJUnit3Test.java, набор тестов должен содержать следующий код.
public JUnit3TestSuite(String testName) {
super(testName);
}
public static Test suite() {
TestSuite suite = new TestSuite("JUnit3TestSuite");
suite.addTest(new TestSuite(sample.VectorsJUnit3Test.class));
suite.addTest(new TestSuite(sample.UtilsJUnit3Test.class));
return suite;
}
Создание набора тестов JUnit 4
Если в качестве версии по умолчанию выбрана версия JUnit 4, в среде IDE могут быть созданы наборы тестов JUnit 4. Версия JUnit 4 совместима с предыдущими версиями, поэтому можно выполнять наборы тестов JUnit 4, содержащие тесты JUnit 4 и JUnit 3. В наборе тестов JUnit 4 указываются тестовые классы для включения их как значений аннотации @Suite.
Для выполнения набора тестов JUnit 3 в составе набора тестов JUnit 4 требуется JUnit 4.4 или выше.
- Щелкните правой кнопкой мыши узел проекта в окне "Projects" и выберите "New > Other" для открытия мастера создания файла.
- Выберите категорию JUnit и "Test Suite". Нажмите кнопку "Next".
- Введите имя файла JUnit4TestSuite.
- Выберите папку sample для создания набора тестов в типовой папке в папке с тестами.
- Снимите флажки "Test Initializer" и "Test Finalizer". Нажмите кнопку "Finish".
При нажатии кнопки "Finish" в среде IDE создается класс набора тестов в папке sample, который затем открывается в редакторе. Набор тестов содержит следующий код.
@RunWith(Suite.class)
@Suite.SuiteClasses(value={UtilsJUnit4Test.class, VectorsJUnit4Test.class})
public class JUnit4TestSuite {
}
При выполнении набора тестов в среде IDE классы теста UtilsJUnit4Test и VectorsJUnit4Test выполняются в указанном порядке.
Выполнение наборов тестов
Набор тестов выполняется аналогично любому отдельному тестовому классу.
- Разверните узел "Test Packages" в окне "Projects".
- Щелкните правой кнопкой мыши класс набора тестов и выберите "Run File".
При выполнении набора тестов в среде IDE тесты, включенные в набор, выполняются в указанном порядке. Результаты отображаются в окне "JUnit Test Results".
В примере на этом рисунке (для увеличения щелкните изображение) в окне отображаются результаты набора тестов JUnit 3. В наборе тестов тестовые классы UtilsJUnit3Test и VectorsJUnit3Test были выполнены как один тест, и результаты выведены на экран в левой панели как результаты одного теста. Данные в правой панели представляют собой результат выполнения тестов по отдельности.
В примере на этом рисунке (для увеличения щелкните изображение) в окне отображаются результаты набора тестов JUnit 4. В наборе тестов тестовые классы UtilsJUnit4Test и VectorsJUnit4Test были выполнены как один тест, и результаты выведены на экран в левой панели как результаты одного теста. Данные в правой панели представляют собой результат выполнения тестов по отдельности.
В примере на этом рисунке (для увеличения щелкните изображение) в окне отображаются результаты смешанного набора тестов. Этот набор тестов включает набор тестов JUnit 4 и один тестовый класс JUnit 3. В наборе тестов тестовые классы UtilsJUnit3Test.java и JUnit4TestSuite.java были выполнены как один тест, и результаты выведены на экран в левой панели как результаты одного теста. Данные в правой панели представляют собой результаты выполнения тестов по отдельности.
Это руководство представляет собой введение в создание модульных тестов JUnit и наборов тестов в среде IDE NetBeans. Тестирование кода позволяет убедиться в том, что небольшие изменения, внесенные в код, не вызовут сбой в работе приложения. Автоматизированные инструментальные средства тестирования, такие как JUnit, рационализируют процесс тестирования, а частое тестирование позволяет выявлять ошибки в коде на ранней стадии.
Дополнительная информация
Для получения дополнительных сведений об использовании среды IDE NetBeans для разработки приложения Java см. следующие материалы:
|
|