Автор оригинала: Pankaj Kumar.
Тестирование-это платформа тестирования для Java-приложений, вдохновленная JUnit и NUnit.
Тестирование
Тестирование предоставляет множество функций, которые упрощают написание и запуск тестовых случаев:
- Аннотации на основе
- Плагины для основных IDE, таких как Eclipse и IDEA.
- Автоматическое создание наборов тестов
- Создание отчетов на основе HTML
- Возможность запуска одного метода тестирования с использованием плагинов IDE.
- Тестирование на основе данных с использованием
@dataProvider
- Никаких дополнительных зависимостей для запуска и ведения журнала
- XML-файл TestNG для запуска наборов тестов с различными конфигурациями
Проверка зависимости Maven
Библиотеки тестирования присутствуют в репозитории maven, вы можете добавить ниже зависимость maven, чтобы включить тестирование в свой проект.
org.testng testng 6.14.3 test
Плагин TestNG Eclipse
Я использую Eclipse для тестирования примера проекта, поэтому давайте сначала установим плагин TestNG Eclipse.
Перейдите в раздел “Eclipse Marketplace” и найдите раздел “Тестирование”.
Нажмите “Установить” и перейдите к дальнейшим экранам, чтобы установить его. Вам придется принять его лицензионное соглашение и перезапустить Eclipse после завершения установки.
Перейдите в раздел “Окно | Показать вид | Другое”, и внутри “Java” вы должны увидеть “Тестирование”.
Это означает, что TestNG для Eclipse успешно установлен, и мы готовы создать наши тестовые классы TestNG.
Создать класс TestNG
Перейдите к своему проекту в проводнике и нажмите “Создать | Другое”, выберите “Класс TestNG” и нажмите “Далее”.
На следующем экране мы должны указать конфигурации нашего класса тестирования, выбрать аннотации для включения в класс и нажать кнопку “Готово”.
Это создаст класс скелета тестирования, как показано ниже.
package com.journaldev.utils; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.AfterSuite; public class TestUtils { @Test(dataProvider = "dp") public void f(Integer n, String s) { } @BeforeMethod public void beforeMethod() { } @AfterMethod public void afterMethod() { } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" }, }; } @BeforeClass public void beforeClass() { } @AfterClass public void afterClass() { } @BeforeTest public void beforeTest() { } @AfterTest public void afterTest() { } @BeforeSuite public void beforeSuite() { } @AfterSuite public void afterSuite() { } }
Вот и все, мы можем запустить наш базовый класс тестирования, перейдя в “Выполнить как | Тестовый тест”, как показано на рисунке ниже.
Поскольку в нашем тестовом классе ничего нет, он должен пройти все тесты. Вы можете проверить “Консоль” на наличие созданных журналов, а “Просмотр тестирования” покажет вам основные сведения о вашем тестовом запуске.
Поток набора тестов TestNG
Я добавил некоторые консольные журналы в аннотированные методы, чтобы понять ход выполнения тестирования.
package com.journaldev.utils; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.BeforeClass; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeSuite; import org.testng.annotations.AfterSuite; public class TestUtils { @Test(dataProvider = "dp") public void f(Integer n, String s) { System.out.println("Inside @Test"); } @BeforeMethod public void beforeMethod() { System.out.println("Inside @BeforeMethod"); } @AfterMethod public void afterMethod() { System.out.println("Inside @AfterMethod"); } @DataProvider public Object[][] dp() { System.out.println("Inside @DataProvider"); return new Object[][] { new Object[] { 1, "a" }, new Object[] { 2, "b" }, }; } @BeforeClass public void beforeClass() { System.out.println("Inside @BeforeClass"); } @AfterClass public void afterClass() { System.out.println("Inside @AfterClass"); } @BeforeTest public void beforeTest() { System.out.println("Inside @BeforeTest"); } @AfterTest public void afterTest() { System.out.println("Inside @AfterTest"); } @BeforeSuite public void beforeSuite() { System.out.println("Inside @BeforeSuite"); } @AfterSuite public void afterSuite() { System.out.println("Inside @AfterSuite"); } }
Когда я запускаю его снова, ниже генерируются журналы консоли.
[RemoteTestNG] detected TestNG version 6.14.3 Inside @BeforeSuite Inside @BeforeTest Inside @BeforeClass Inside @DataProvider Inside @BeforeMethod Inside @Test Inside @AfterMethod Inside @BeforeMethod Inside @Test Inside @AfterMethod Inside @AfterClass Inside @AfterTest PASSED: f(1, "a") PASSED: f(2, "b") =============================================== Default test Tests run: 2, Failures: 0, Skips: 0 =============================================== Inside @AfterSuite =============================================== Default suite Total tests run: 2, Failures: 0, Skips: 0 ===============================================
Основываясь на приведенных выше выводах, мы можем вывести поток тестирования теста как:
BeforeSuite -> BeforeTest -> BeforeClass -> DataProvider -> { BeforeMethod -> Test -> AfterMethod } * N -> AfterClass -> AfterTest -> AfterSuite
N-это количество раз, когда выполняется наш метод тестирования, и это зависит от количества входных данных, сгенерированных методом @dataProvider
.
Мы можем использовать методы @BeforeXXX
для некоторой предварительной обработки и инициализации ресурсов, которые мы хотим использовать в наборе тестов. Аналогично, мы можем использовать @AfterXXX
методы для последующей обработки и закрытия ресурсов.
Учебное пособие по тестированию
Теперь, когда мы ознакомились с основами тестирования и настроили его в Eclipse, давайте создадим класс с несколькими методами и используем TestNG для запуска некоторых тестовых случаев на нем.
package com.journaldev.utils; public class Utils { public static String NAME = ""; public int add(int x, int y) { return x + y; } public int subtract(int x, int y) { return x - y; } public static void setName(String s) { System.out.println("Setting NAME to " + s); NAME = s; } }
Я добавил несколько общедоступных методов, а также статические и пустые методы. Ниже приведен мой класс TestNG для тестирования этих методов.
package com.journaldev.utils; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestUtils { @Test(dataProvider = "dp") public void test_add(Integer x, Integer y) { Utils u = new Utils(); Assert.assertEquals(u.add(x, y), x + y); } @Test(dataProvider = "dp") public void test_subtract(Integer x, Integer y) { Utils u = new Utils(); Assert.assertEquals(u.subtract(x, y), x - y); } @Test(dataProvider = "dpName") public void test_setName(String s) { Utils.setName(s); Assert.assertEquals(Utils.NAME, s); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 1, 1 }, new Object[] { 2, 2 }, }; } @DataProvider public Object[][] dpName() { return new Object[][] { new Object[] { "Utils" }, new Object[] { "MyUtils" }, }; } }
Теперь, когда мы запускаем выше класса в качестве теста TestNG, мы получаем следующий вывод в консоли.
[RemoteTestNG] detected TestNG version 6.14.3 Setting NAME to Utils Setting NAME to MyUtils PASSED: test_add(1, 1) PASSED: test_add(2, 2) PASSED: test_setName("Utils") PASSED: test_setName("MyUtils") PASSED: test_subtract(1, 1) PASSED: test_subtract(2, 2) =============================================== Default test Tests run: 6, Failures: 0, Skips: 0 =============================================== =============================================== Default suite Total tests run: 6, Failures: 0, Skips: 0 ===============================================
Обновите проект, и вы увидите вновь созданный каталог тестовый вывод
.
Открыть index.html
в любом браузере, и вы должны увидеть HTML-отчет, как показано на рисунке ниже.
Набор XML-тестов TestNG
Одной из лучших частей тестирования является автоматическое создание xml-файла набора тестов.
Мы можем отредактировать его и добавить в него параметры, мы также можем использовать его для запуска одного метода тестирования. XML-пакет TestNG предоставляет множество опций, и он очень полезен, когда вы хотите запустить тестовый случай через командную строку, например, на сервере без Eclipse. Мы можем запустить xml-файл набора тестов TestNG, используя приведенную ниже команду:
$java com.journaldev.utils.TestUtils testng.xml
TestNG XML-очень обширная тема, если вы хотите изучить ее подробнее, просмотрите ее документацию .
Тестирование Выполняется Одним Методом Тестирования
Мы также можем запустить один метод тестирования, это очень полезно, когда в нашем тестовом классе много методов, и мы заинтересованы только в том, чтобы протестировать несколько из них.
Тестирование Тестирование с ошибками
Давайте посмотрим, что произойдет, когда в нашем коде появится ошибка, измените метод Utils
class setName
, как показано ниже.
public static void setName(String s) { System.out.println("Setting NAME to " + s); // NAME = s; //introducing bug intentionally }
Теперь, когда мы снова запускаем тестовый класс, мы получаем следующий вывод в консоли.
[RemoteTestNG] detected TestNG version 6.14.3 Setting NAME to Utils Setting NAME to MyUtils FAILED: test_setName("Utils") java.lang.AssertionError: expected [Utils] but found [] at org.testng.Assert.fail(Assert.java:96) at org.testng.Assert.failNotEquals(Assert.java:776) at org.testng.Assert.assertEqualsImpl(Assert.java:137) at org.testng.Assert.assertEquals(Assert.java:118) at org.testng.Assert.assertEquals(Assert.java:453) at org.testng.Assert.assertEquals(Assert.java:463) at com.journaldev.utils.TestUtils.test_setName(TestUtils.java:23) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124) at org.testng.internal.Invoker.invokeMethod(Invoker.java:583) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) at org.testng.TestRunner.privateRun(TestRunner.java:648) at org.testng.TestRunner.run(TestRunner.java:505) at org.testng.SuiteRunner.runTest(SuiteRunner.java:455) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415) at org.testng.SuiteRunner.run(SuiteRunner.java:364) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208) at org.testng.TestNG.runSuitesLocally(TestNG.java:1137) at org.testng.TestNG.runSuites(TestNG.java:1049) at org.testng.TestNG.run(TestNG.java:1017) at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77) FAILED: test_setName("MyUtils") java.lang.AssertionError: expected [MyUtils] but found [] at org.testng.Assert.fail(Assert.java:96) at org.testng.Assert.failNotEquals(Assert.java:776) at org.testng.Assert.assertEqualsImpl(Assert.java:137) at org.testng.Assert.assertEquals(Assert.java:118) at org.testng.Assert.assertEquals(Assert.java:453) at org.testng.Assert.assertEquals(Assert.java:463) at com.journaldev.utils.TestUtils.test_setName(TestUtils.java:23) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124) at org.testng.internal.Invoker.invokeMethod(Invoker.java:583) at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719) at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989) at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125) at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) at org.testng.TestRunner.privateRun(TestRunner.java:648) at org.testng.TestRunner.run(TestRunner.java:505) at org.testng.SuiteRunner.runTest(SuiteRunner.java:455) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415) at org.testng.SuiteRunner.run(SuiteRunner.java:364) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208) at org.testng.TestNG.runSuitesLocally(TestNG.java:1137) at org.testng.TestNG.runSuites(TestNG.java:1049) at org.testng.TestNG.run(TestNG.java:1017) at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)
Вы заметили, что я запускаю тест только для метода setName.:)
Запуск тестов TestNG из командной строки
Хорошо, что мы можем запускать наши тестовые случаи из Eclipse, но в большинстве случаев мы хотим запускать все тестовые случаи проекта при его создании. Что ж, maven автоматически запускает тестовые примеры для нас. На изображениях ниже показан вывод команды mvn clean install
.
Пример Успеха
Случай Отказа
Порядок Тестирования Тестовых Случаев
Тестовые случаи тестирования выполняются в порядке их имен методов. Таким образом, в нашем случае порядок выполнения будет следующим: test_add -> test_setName -> test_subtract
.
Мы можем изменить порядок, установив приоритет
методов тестирования. Если нам нужен порядок выполнения как test_add -> test_subtract -> Имя набора тестов
, мы можем изменить нашу аннотацию @Test, как показано ниже.
@Test(dataProvider = "dp", priority=1) public void test_add(Integer x, Integer y) { } @Test(dataProvider = "dp", priority=2) public void test_subtract(Integer x, Integer y) { } @Test(dataProvider = "dpName", priority=3) public void test_setName(String s) { }
Обратите внимание, что сначала выполняются методы с более низким приоритетом.
Резюме
Тестирование-очень популярная платформа модульного тестирования, и мне очень понравилось, что ее очень легко настроить и использовать в проекте. Мы изучили основы тестирования и рассмотрели наиболее распространенные примеры его использования в нашем проекте.