HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#статьи</a></p>
1 <p><a>#статьи</a></p>
2 <ul><li>11 сен 2023</li>
2 <ul><li>11 сен 2023</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><p>Изучаем главный инструмент тестировщика приложений на Java и пишем первую программу по методологии TDD.</p>
4 </ul><p>Изучаем главный инструмент тестировщика приложений на Java и пишем первую программу по методологии TDD.</p>
5 <p>Иллюстрация: Оля Ежак для Skillbox Media</p>
5 <p>Иллюстрация: Оля Ежак для Skillbox Media</p>
6 <p>Пишет о сетях, инструментах для разработчиков и языках программирования. Любит готовить, играть в инди‑игры и программировать на Python.</p>
6 <p>Пишет о сетях, инструментах для разработчиков и языках программирования. Любит готовить, играть в инди‑игры и программировать на Python.</p>
7 <p>Пока приложение или сайт небольшие, для контроля качества достаточно мануальных тестировщиков, проверяющих работу "руками". Но что делать, когда в приложении уже сотни файлов и десятки тысяч строк кода? Тестировать вручную становится долго и дорого.</p>
7 <p>Пока приложение или сайт небольшие, для контроля качества достаточно мануальных тестировщиков, проверяющих работу "руками". Но что делать, когда в приложении уже сотни файлов и десятки тысяч строк кода? Тестировать вручную становится долго и дорого.</p>
8 <p>Для таких случаев используют специальные тестовые фреймворки. Один из них - JUnit, фреймворк для модульного тестирования Java-приложений. Он позволяет проводить автоматизированные юнит- и интеграционные тесты.</p>
8 <p>Для таких случаев используют специальные тестовые фреймворки. Один из них - JUnit, фреймворк для модульного тестирования Java-приложений. Он позволяет проводить автоматизированные юнит- и интеграционные тесты.</p>
9 <p>Из этой статьи вы узнаете:</p>
9 <p>Из этой статьи вы узнаете:</p>
10 <ul><li><a>что такое JUnit</a>;</li>
10 <ul><li><a>что такое JUnit</a>;</li>
11 <li><a>какие аннотации в нём используются</a>;</li>
11 <li><a>какие аннотации в нём используются</a>;</li>
12 <li><a>в чём разница между JUnit4 и JUnit5</a>;</li>
12 <li><a>в чём разница между JUnit4 и JUnit5</a>;</li>
13 <li><a>как установить JUnit</a>;</li>
13 <li><a>как установить JUnit</a>;</li>
14 <li><a>как он работает</a>;</li>
14 <li><a>как он работает</a>;</li>
15 <li><a>что такое test-driven development</a>;</li>
15 <li><a>что такое test-driven development</a>;</li>
16 <li><a>как написать приложение по принципам TDD</a>.</li>
16 <li><a>как написать приложение по принципам TDD</a>.</li>
17 </ul><p>JUnit - фреймворк для автоматического юнит-тестирования приложений. Он содержит специальные функции и правила, которые позволяют легко писать и запускать тесты, то есть проверять, что каждый блок кода, или модуль, ответственный за определённую функцию программы, работает как надо. Такой вид тестирования называют модульным, или юнит-тестированием.</p>
17 </ul><p>JUnit - фреймворк для автоматического юнит-тестирования приложений. Он содержит специальные функции и правила, которые позволяют легко писать и запускать тесты, то есть проверять, что каждый блок кода, или модуль, ответственный за определённую функцию программы, работает как надо. Такой вид тестирования называют модульным, или юнит-тестированием.</p>
18 <p>Последняя версия фреймворка -<a>JUnit 5</a>. Она состоит из трёх модулей: JUnit Platform, JUnit Jupiter и JUnit Vintage.</p>
18 <p>Последняя версия фреймворка -<a>JUnit 5</a>. Она состоит из трёх модулей: JUnit Platform, JUnit Jupiter и JUnit Vintage.</p>
19 <p><strong>JUnit Platform</strong> - основной модуль для управления тестами.</p>
19 <p><strong>JUnit Platform</strong> - основной модуль для управления тестами.</p>
20 <p><strong>JUnit Jupiter</strong> - модуль, который использует новые возможности Java 8. Он предоставляет API на основе аннотаций и позволяет работать с модульными и динамическими тестами.</p>
20 <p><strong>JUnit Jupiter</strong> - модуль, который использует новые возможности Java 8. Он предоставляет API на основе аннотаций и позволяет работать с модульными и динамическими тестами.</p>
21 <p><strong>JUnit Vintage</strong> - модуль для поддержки тестов, написанных с использованием JUnit 3 и JUnit 4.</p>
21 <p><strong>JUnit Vintage</strong> - модуль для поддержки тестов, написанных с использованием JUnit 3 и JUnit 4.</p>
22 <p>JUnit удобен тем, что разработчик может гибко указывать условия тестирования. Например, объединять тесты в группы, распределяя их по функциональности, тестируемым модулям или уровню критичности, прописывать условия запуска для каждого блока кода и анализировать результаты по отдельности. Всё это облегчает работу программиста или QA-инженера.</p>
22 <p>JUnit удобен тем, что разработчик может гибко указывать условия тестирования. Например, объединять тесты в группы, распределяя их по функциональности, тестируемым модулям или уровню критичности, прописывать условия запуска для каждого блока кода и анализировать результаты по отдельности. Всё это облегчает работу программиста или QA-инженера.</p>
23 <p>Аннотации в JUnit - это специальные метки, которые Java-разработчик размещает перед методами в тестовом классе. Они позволяют настраивать процесс тестирования, указывая фреймворку, как именно их следует обрабатывать. Например, можно явно указать, какие из методов являются тестовыми случаями, какие из них выполнять перед тестами и после и так далее.</p>
23 <p>Аннотации в JUnit - это специальные метки, которые Java-разработчик размещает перед методами в тестовом классе. Они позволяют настраивать процесс тестирования, указывая фреймворку, как именно их следует обрабатывать. Например, можно явно указать, какие из методов являются тестовыми случаями, какие из них выполнять перед тестами и после и так далее.</p>
24 <p>Вот несколько базовых аннотаций.</p>
24 <p>Вот несколько базовых аннотаций.</p>
25 <p>@Test. Эту аннотацию ставим перед методами, которые относятся к тестовым случаям. JUnit поймёт, что их следует выполнять в качестве теста, а по завершении проверить результат.</p>
25 <p>@Test. Эту аннотацию ставим перед методами, которые относятся к тестовым случаям. JUnit поймёт, что их следует выполнять в качестве теста, а по завершении проверить результат.</p>
26 <p>@Before. Используется для методов, которые должны быть выполнены перед каждым тестовым случаем. Например, если у нас есть несколько тестов, которые требуют одних и тех же начальных условий, мы можем обозначить метод с аннотацией @Before, задав необходимые условия тестирования один раз.</p>
26 <p>@Before. Используется для методов, которые должны быть выполнены перед каждым тестовым случаем. Например, если у нас есть несколько тестов, которые требуют одних и тех же начальных условий, мы можем обозначить метод с аннотацией @Before, задав необходимые условия тестирования один раз.</p>
27 <p>@After. Эту аннотацию используем перед методом, который должен быть выполнен после тестового случая.</p>
27 <p>@After. Эту аннотацию используем перед методом, который должен быть выполнен после тестового случая.</p>
28 <p>@BeforeClass, @AfterClass. Методы с аннотацией @BeforeClass выполняются перед запуском первого теста в классе, а методы с аннотацией @AfterClass - после завершения всех тестов в классе.</p>
28 <p>@BeforeClass, @AfterClass. Методы с аннотацией @BeforeClass выполняются перед запуском первого теста в классе, а методы с аннотацией @AfterClass - после завершения всех тестов в классе.</p>
29 <p>@Ignore. Используется перед методом, чтобы отключить его выполнение в тесте. Это может быть полезно, если мы не уверены в работоспособности отдельных тестов и не хотим их использовать, но должны оставить в коде.</p>
29 <p>@Ignore. Используется перед методом, чтобы отключить его выполнение в тесте. Это может быть полезно, если мы не уверены в работоспособности отдельных тестов и не хотим их использовать, но должны оставить в коде.</p>
30 <p>@BeforeEach и @AfterEach. Аналоги @Before и @After в JUnit 4.</p>
30 <p>@BeforeEach и @AfterEach. Аналоги @Before и @After в JUnit 4.</p>
31 <p>Полный список аннотаций с подробными объяснениями и примерами использования можно прочесть в <a>документации</a>.</p>
31 <p>Полный список аннотаций с подробными объяснениями и примерами использования можно прочесть в <a>документации</a>.</p>
32 <p>Вот как аннотации выглядят в коде:</p>
32 <p>Вот как аннотации выглядят в коде:</p>
33 import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.AfterEach; public class MyTest { @BeforeEach public void setUp() { // Метод, выполняющийся перед каждым тестовым случаем } @AfterEach public void tearDown() { // Метод, выполняющийся после каждого тестового случая } @Test public void testSomething() { // Тестовый случай } @Test public void testAnotherThing() { // Другой тестовый случай } }<p>JUnit 4 и JUnit 5 - это две последние версии фреймворка JUnit, которые сейчас распространены в разработке. Между собой они различаются функциональностью, синтаксисом и возможностями.</p>
33 import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.AfterEach; public class MyTest { @BeforeEach public void setUp() { // Метод, выполняющийся перед каждым тестовым случаем } @AfterEach public void tearDown() { // Метод, выполняющийся после каждого тестового случая } @Test public void testSomething() { // Тестовый случай } @Test public void testAnotherThing() { // Другой тестовый случай } }<p>JUnit 4 и JUnit 5 - это две последние версии фреймворка JUnit, которые сейчас распространены в разработке. Между собой они различаются функциональностью, синтаксисом и возможностями.</p>
34 <p>Тестовые методы в JUnit 4 помечаются аннотацией @Test. Для определения методов, выполняющихся до и после тестового случая, используют аннотации @Before и @After.</p>
34 <p>Тестовые методы в JUnit 4 помечаются аннотацией @Test. Для определения методов, выполняющихся до и после тестового случая, используют аннотации @Before и @After.</p>
35 <p>В этой версии фреймворка поддерживаются параметризованные тесты с использованием аннотации @RunWith(Parameterized.class). Это значит, что в тест можно передать параметры, необходимые для тестирования.</p>
35 <p>В этой версии фреймворка поддерживаются параметризованные тесты с использованием аннотации @RunWith(Parameterized.class). Это значит, что в тест можно передать параметры, необходимые для тестирования.</p>
36 <p>Тесты, написанные на JUnit 4, могут выполняться в JUnit 5 с использованием JUnit Vintage.</p>
36 <p>Тесты, написанные на JUnit 4, могут выполняться в JUnit 5 с использованием JUnit Vintage.</p>
37 <p>В пятой версии фреймворка появились новые модули:<a>Jupiter</a> - для тестирования с использованием возможностей Java 8, и <a>Platform</a> - модуль для запуска тестов.</p>
37 <p>В пятой версии фреймворка появились новые модули:<a>Jupiter</a> - для тестирования с использованием возможностей Java 8, и <a>Platform</a> - модуль для запуска тестов.</p>
38 <p>Также в JUnit 5 появилась возможность писать собственные расширения для тестов и запускать их по аннотации @ExtendWith. По аналогии с JUnit 4 поддерживаются параметризованные тесты с аннотацией @ParameterizedTest.</p>
38 <p>Также в JUnit 5 появилась возможность писать собственные расширения для тестов и запускать их по аннотации @ExtendWith. По аналогии с JUnit 4 поддерживаются параметризованные тесты с аннотацией @ParameterizedTest.</p>
39 <p>В примерах с кодом мы будем использовать JUnit 5 - это современная версия фреймворка, которая поддерживает Java 8 и JUnit 4.</p>
39 <p>В примерах с кодом мы будем использовать JUnit 5 - это современная версия фреймворка, которая поддерживает Java 8 и JUnit 4.</p>
40 <p>Всё просто - добавляем необходимую зависимость в конфигурационный файл сборщика.</p>
40 <p>Всё просто - добавляем необходимую зависимость в конфигурационный файл сборщика.</p>
41 <p><strong>Для</strong><a><strong>Maven</strong></a><strong>:</strong></p>
41 <p><strong>Для</strong><a><strong>Maven</strong></a><strong>:</strong></p>
42 <ul><li>Зайдите в файл pom.xml.</li>
42 <ul><li>Зайдите в файл pom.xml.</li>
43 <li>Найдите секцию &lt;dependencies&gt;.</li>
43 <li>Найдите секцию &lt;dependencies&gt;.</li>
44 <li>Добавьте внутрь блок:</li>
44 <li>Добавьте внутрь блок:</li>
45 </ul>&lt;dependency&gt; &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt; &lt;artifactId&gt;junit-jupiter-api&lt;/artifactId&gt; &lt;version&gt;5.8.2&lt;/version&gt; &lt;!-- Версия может быть другой, актуальную версию смотрите на сайте JUnit --&gt; &lt;scope&gt;test&lt;/scope&gt; &lt;/dependency&gt;<ul><li>Сохраните изменения.</li>
45 </ul>&lt;dependency&gt; &lt;groupId&gt;org.junit.jupiter&lt;/groupId&gt; &lt;artifactId&gt;junit-jupiter-api&lt;/artifactId&gt; &lt;version&gt;5.8.2&lt;/version&gt; &lt;!-- Версия может быть другой, актуальную версию смотрите на сайте JUnit --&gt; &lt;scope&gt;test&lt;/scope&gt; &lt;/dependency&gt;<ul><li>Сохраните изменения.</li>
46 </ul><p><strong>Для Gradle:</strong></p>
46 </ul><p><strong>Для Gradle:</strong></p>
47 <ul><li>Зайдите в build.gradle.</li>
47 <ul><li>Зайдите в build.gradle.</li>
48 <li>Найдите секцию dependencies.</li>
48 <li>Найдите секцию dependencies.</li>
49 <li>Добавьте внутрь блок с кодом:</li>
49 <li>Добавьте внутрь блок с кодом:</li>
50 </ul>testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'<p>Важно, что при работе с Gradle необходимо указать версию фреймворка. Мы рекомендуем использовать наиболее актуальную. Посмотреть её можно на <a>главной странице сайта</a>под заголовком Latest Release.</p>
50 </ul>testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'<p>Важно, что при работе с Gradle необходимо указать версию фреймворка. Мы рекомендуем использовать наиболее актуальную. Посмотреть её можно на <a>главной странице сайта</a>под заголовком Latest Release.</p>
51 <ul><li>Сохраните изменения.</li>
51 <ul><li>Сохраните изменения.</li>
52 </ul><p>Напишем на Java простой калькулятор:</p>
52 </ul><p>Напишем на Java простой калькулятор:</p>
53 public class Calculator { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int divide(int a, int b) { if (b == 0) { throw new IllegalArgumentException("Cannot divide by zero"); } return a / b; } }<p>Для модульного тестирования калькулятора нам требуется написать отдельные тесты для сложения, вычитания, умножения и два теста для деления. С JUnit код будет такой:</p>
53 public class Calculator { public int add(int a, int b) { return a + b; } public int subtract(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } public int divide(int a, int b) { if (b == 0) { throw new IllegalArgumentException("Cannot divide by zero"); } return a / b; } }<p>Для модульного тестирования калькулятора нам требуется написать отдельные тесты для сложения, вычитания, умножения и два теста для деления. С JUnit код будет такой:</p>
54 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class CalculatorTest { @Test public void testAddition() { Calculator calculator = new Calculator(); int result = calculator.add(3, 5); assertEquals(8, result); } @Test public void testSubtraction() { Calculator calculator = new Calculator(); int result = calculator.subtract(10, 4); assertEquals(6, result); } @Test public void testMultiplication() { Calculator calculator = new Calculator(); int result = calculator.multiply(6, 3); assertEquals(18, result); } @Test public void testDivision() { Calculator calculator = new Calculator(); int result = calculator.divide(10, 2); assertEquals(5, result); } @Test public void testDivisionByZero() { Calculator calculator = new Calculator(); assertThrows(IllegalArgumentException.class, () -&gt; { calculator.divide(10, 0); }); } }<p>Разберем его:</p>
54 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class CalculatorTest { @Test public void testAddition() { Calculator calculator = new Calculator(); int result = calculator.add(3, 5); assertEquals(8, result); } @Test public void testSubtraction() { Calculator calculator = new Calculator(); int result = calculator.subtract(10, 4); assertEquals(6, result); } @Test public void testMultiplication() { Calculator calculator = new Calculator(); int result = calculator.multiply(6, 3); assertEquals(18, result); } @Test public void testDivision() { Calculator calculator = new Calculator(); int result = calculator.divide(10, 2); assertEquals(5, result); } @Test public void testDivisionByZero() { Calculator calculator = new Calculator(); assertThrows(IllegalArgumentException.class, () -&gt; { calculator.divide(10, 0); }); } }<p>Разберем его:</p>
55 <p><strong>import org.junit.jupiter.api.Test;</strong> - здесь мы импортировали аннотацию Test из фреймворка JUnit. Она помечает методы как тестовые случаи, определяя их выполнение во время запуска тестов.</p>
55 <p><strong>import org.junit.jupiter.api.Test;</strong> - здесь мы импортировали аннотацию Test из фреймворка JUnit. Она помечает методы как тестовые случаи, определяя их выполнение во время запуска тестов.</p>
56 <p><strong>import static org.junit.jupiter.api.Assertions.*;</strong> - импортировали статические методы утверждений (assertions) из класса Assert - assertEquals(expected, actual). Они сравнивают ожидаемые и фактические результаты тестов. Если результаты не совпадают, то тест считается не пройденным.</p>
56 <p><strong>import static org.junit.jupiter.api.Assertions.*;</strong> - импортировали статические методы утверждений (assertions) из класса Assert - assertEquals(expected, actual). Они сравнивают ожидаемые и фактические результаты тестов. Если результаты не совпадают, то тест считается не пройденным.</p>
57 <p><strong>public class CalculatorTest {… }</strong> - определили класс для наших тестов.</p>
57 <p><strong>public class CalculatorTest {… }</strong> - определили класс для наших тестов.</p>
58 <p>Далее мы прописали тестовые методы, например testAddition(), testSubtraction(), testMultiplication(), public void testDivision(). Внутри каждого метода тестируем конкретную арифметическую операцию. Для этого мы сравниваем результат работы калькулятора с заранее подобранным правильным ответом с помощью assertEquals.</p>
58 <p>Далее мы прописали тестовые методы, например testAddition(), testSubtraction(), testMultiplication(), public void testDivision(). Внутри каждого метода тестируем конкретную арифметическую операцию. Для этого мы сравниваем результат работы калькулятора с заранее подобранным правильным ответом с помощью assertEquals.</p>
59 <p>Для каждого теста создали экземпляр класса Calculator, который будет использоваться для их проведения.</p>
59 <p>Для каждого теста создали экземпляр класса Calculator, который будет использоваться для их проведения.</p>
60 <p>В этом примере мы сначала написали программу, а потом - тесты для неё. Но иногда разработчики используют другой подход.</p>
60 <p>В этом примере мы сначала написали программу, а потом - тесты для неё. Но иногда разработчики используют другой подход.</p>
61 <p>Test-driven development (TDD) - это подход к разработке программ, при котором разработчик сначала описывает тесты для функции, которую хочет создать, а затем пишет сам код, который проходит эти тесты.</p>
61 <p>Test-driven development (TDD) - это подход к разработке программ, при котором разработчик сначала описывает тесты для функции, которую хочет создать, а затем пишет сам код, который проходит эти тесты.</p>
62 <p>При таком подходе главные издержки разработки - время на рефакторинг и исправление ошибок - снижаются. А значит, уменьшаются и затраты на создание и поддержку продукта.</p>
62 <p>При таком подходе главные издержки разработки - время на рефакторинг и исправление ошибок - снижаются. А значит, уменьшаются и затраты на создание и поддержку продукта.</p>
63 <p>Упрощённо TDD можно представить в виде нескольких шагов:</p>
63 <p>Упрощённо TDD можно представить в виде нескольких шагов:</p>
64 <ul><li><strong>Написание теста.</strong>Разработчик начинает работу с создания теста, который будет проверять работоспособность кода.</li>
64 <ul><li><strong>Написание теста.</strong>Разработчик начинает работу с создания теста, который будет проверять работоспособность кода.</li>
65 <li><strong>Запуск теста.</strong>При первом запуске тест не должен быть пройден, так как функционального кода программы ещё нет.</li>
65 <li><strong>Запуск теста.</strong>При первом запуске тест не должен быть пройден, так как функционального кода программы ещё нет.</li>
66 <li><strong>Написание кода.</strong>Разработчик пишет код с минимальной функциональностью, которая позволяет успешно пройти тест.</li>
66 <li><strong>Написание кода.</strong>Разработчик пишет код с минимальной функциональностью, которая позволяет успешно пройти тест.</li>
67 <li><strong>Повторный запуск теста.</strong>При повторном запуске тест должен быть пройден удачно.</li>
67 <li><strong>Повторный запуск теста.</strong>При повторном запуске тест должен быть пройден удачно.</li>
68 <li><strong>Рефакторинг.</strong>После успешного завершения тестов разработчик может приступить к рефакторингу - улучшению и оптимизации кода. Важно, что после каждого изменения запуск теста повторяется.</li>
68 <li><strong>Рефакторинг.</strong>После успешного завершения тестов разработчик может приступить к рефакторингу - улучшению и оптимизации кода. Важно, что после каждого изменения запуск теста повторяется.</li>
69 </ul><p>Каждый функциональный модуль, который добавляется в приложение, должен пройти эти этапы. Таким образом, разработчик уже в процессе написания отдельных частей программы подтверждает, что они успешно проходят тесты.</p>
69 </ul><p>Каждый функциональный модуль, который добавляется в приложение, должен пройти эти этапы. Таким образом, разработчик уже в процессе написания отдельных частей программы подтверждает, что они успешно проходят тесты.</p>
70 <p>Используя подход TDD, создадим простое приложение - программу для вычисления факториала числа. Сначала напишем тесты, а затем функциональный код.</p>
70 <p>Используя подход TDD, создадим простое приложение - программу для вычисления факториала числа. Сначала напишем тесты, а затем функциональный код.</p>
71 <p>Работать будем в среде разработки IntelliJ IDEA с Maven на борту. Как создать и инициализировать проект в Maven и подключить JUnit,<a>смотрите выше</a>. А мы перейдём к коду.</p>
71 <p>Работать будем в среде разработки IntelliJ IDEA с Maven на борту. Как создать и инициализировать проект в Maven и подключить JUnit,<a>смотрите выше</a>. А мы перейдём к коду.</p>
72 <p>Создайте файл для тестов в папке test\java. У нас он будет называться NumberUtilTest.java.</p>
72 <p>Создайте файл для тестов в папке test\java. У нас он будет называться NumberUtilTest.java.</p>
73 <em>Скриншот: Skillbox Media</em><p>Напишите тест для функции вычисления факториала, по аналогии с тестированием калькулятора:</p>
73 <em>Скриншот: Skillbox Media</em><p>Напишите тест для функции вычисления факториала, по аналогии с тестированием калькулятора:</p>
74 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class NumberUtilTest { @Test public void testFactorial() { NumberUtil util = new NumberUtil(); int result = util.factorial(5); // Определяем факториал числа 5 assertEquals(120, result); // Сравниваем результат с правильным ответом } }<p>Основываясь на тесте, пропишите в папке main/java класс с названием NumberUtil. Класс пока что оставьте пустым:</p>
74 import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; public class NumberUtilTest { @Test public void testFactorial() { NumberUtil util = new NumberUtil(); int result = util.factorial(5); // Определяем факториал числа 5 assertEquals(120, result); // Сравниваем результат с правильным ответом } }<p>Основываясь на тесте, пропишите в папке main/java класс с названием NumberUtil. Класс пока что оставьте пустым:</p>
75 <em>Скриншот: Skillbox Media</em><p>Запустим наш тест:</p>
75 <em>Скриншот: Skillbox Media</em><p>Запустим наш тест:</p>
76 <em>Скриншот: Skillbox Media</em><p>Тест не пройден. Пока так и должно быть - наш класс ничего не содержит:</p>
76 <em>Скриншот: Skillbox Media</em><p>Тест не пройден. Пока так и должно быть - наш класс ничего не содержит:</p>
77 <em>Скриншот: Skillbox Media</em><p>Теперь реализуйте функцию factorial в классе NumberUtil, чтобы тест прошёл успешно:</p>
77 <em>Скриншот: Skillbox Media</em><p>Теперь реализуйте функцию factorial в классе NumberUtil, чтобы тест прошёл успешно:</p>
78 public class NumberUtil { public int factorial(int n) { if (n &lt; 0) { throw new IllegalArgumentException("Факториал не может быть рассчитан для отрицательных чисел"); } if (n == 0 || n == 1) { return 1; } return n * factorial(n - 1); } }<p>Запустите тест снова. Если вы всё сделали правильно, то он пройдёт успешно:</p>
78 public class NumberUtil { public int factorial(int n) { if (n &lt; 0) { throw new IllegalArgumentException("Факториал не может быть рассчитан для отрицательных чисел"); } if (n == 0 || n == 1) { return 1; } return n * factorial(n - 1); } }<p>Запустите тест снова. Если вы всё сделали правильно, то он пройдёт успешно:</p>
79 <em>Скриншот: Skillbox Media</em><p>Поздравляем! Вы написали приложение, используя метод TDD для тестирования и разработки.</p>
79 <em>Скриншот: Skillbox Media</em><p>Поздравляем! Вы написали приложение, используя метод TDD для тестирования и разработки.</p>
80 <a>Научитесь: Профессия Java-разработчик + ИИ Узнать больше</a>
80 <a>Научитесь: Профессия Java-разработчик + ИИ Узнать больше</a>