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


135

У меня есть класс Java. Как я могу протестировать это?


В моем случае у меня класс делает двоичную сумму. Он берет два byte[]массива, суммирует их и возвращает новый двоичный массив.


7
Вы можете использовать такой инструмент, как jUnit и писать тестовые примеры (методы тестирования) для вашего java-класса. Затем вызовите тесты jUnit как часть процесса сборки (ant / maven). Использование jUnit совсем не сложно, сложная часть заключается в том, чтобы придумать как можно больше тестовых сценариев, чтобы вы могли своевременно и часто обнаруживать ошибки.
CoolBeans

Ответы:


133
  1. Определите ожидаемый и желаемый результат для нормального случая с правильным вводом.

  2. Теперь реализуйте тест, объявив класс, назовите его как угодно (обычно что-то вроде TestAddingModule) и добавьте к нему метод testAdd (то есть, как показано ниже):

    • Напишите метод, а над ним добавьте аннотацию @Test.
    • В методе запустите свою двоичную сумму и assertEquals(expectedVal,calculatedVal).
    • Проверьте свой метод, запустив его (в Eclipse щелкните правой кнопкой мыши, выберите Run as → JUnit test).

      //for normal addition 
      @Test
      public void testAdd1Plus1() 
      {
          int x  = 1 ; int y = 1;
          assertEquals(2, myClass.add(x,y));
      }
  3. Добавьте другие случаи по желанию.

    • Проверьте, что ваша двоичная сумма не выдает неожиданное исключение, если есть целочисленное переполнение.
    • Проверьте, что ваш метод корректно обрабатывает нулевые значения (пример ниже).

      //if you are using 0 as default for null, make sure your class works in that case.
      @Test
      public void testAdd1Plus1() 
      {
          int y = 1;
          assertEquals(0, myClass.add(null,y));
      }

1. требуется ли нотация @Test? 2. почему бы не проверить нулевой ввод с помощью assertNotNull? 3. где фиксируются результаты юнит-тестов? как результаты отображаются для пользователя?
user137717

10
Да, @Testзапись обязательна. Это делается для того, чтобы сообщить организатору модульного теста, что этот метод представляет собой модульный тест и его следует выполнить. Методы, которые не аннотированы @Test, не выполняются исполнителем теста.
Али Шах Ахмед

для второго теста - не следует ли добавить, nullчтобы yпросто дать вам y?
Отрегулируйте

Спасибо! Я хочу знать, почему нет необходимости добавлять staticв модификатор метода испытаний.
Лян Чжан

104

Я предоставляю этот пост как для IntelliJ, так и для Eclipse .

Затмение:

Для создания модульного теста для вашего проекта, пожалуйста, выполните следующие действия (я использую Eclipse для написания этого теста):

1- Нажмите New -> Java Project.

Создать проект

2. Запишите название вашего проекта и нажмите «Готово».

Создать проект

3- Щелкните правой кнопкой мыши по вашему проекту. Затем нажмите New -> Class.

Создать класс

4- Запишите имя своего класса и нажмите «Готово».

Создать класс

Затем завершите класс следующим образом:

public class Math {
    int a, b;
    Math(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int add() {
        return a + b;
    }
}

5- Нажмите Файл -> Создать -> Тестовый пример JUnit.

Создать JUnite Test

6- Проверьте setUp () и нажмите на готово. SetUp () будет местом, где вы инициализируете свой тест.

Проверьте SetUp ()

7- Нажмите на ОК.

Добавить JUnit

8. Здесь я просто добавляю 7 и 10. Итак, я ожидаю, что ответ будет 17. Пройдите свой тестовый класс следующим образом:

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MathTest {
    Math math;
    @Before
    public void setUp() throws Exception {
        math = new Math(7, 10);
    }
    @Test
    public void testAdd() {
        Assert.assertEquals(17, math.add());
    }
}

9- Напишите, нажмите на ваш тестовый класс в проводнике пакетов и нажмите Run as -> JUnit Test.

Запустите тест JUnit

10- Это результат теста.

Результат теста

IntelliJ: Обратите внимание, что я использовал IntelliJ IDEA community 2020.1 для скриншотов. Кроме того, вам нужно настроить свой JRE перед этими шагами. Я использую JDK 11.0.4.

1- Щелкните правой кнопкой мыши на главной папке вашего проекта -> новый -> каталог. Вы должны назвать это «тест». введите описание изображения здесь 2- Щелкните правой кнопкой мыши на тестовой папке и создайте соответствующий пакет. Я предлагаю создать те же названия упаковки, что и в оригинальном классе. Затем щелкните правой кнопкой мыши на тестовой директории -> пометить директорию как -> корень тестовых источников. введите описание изображения здесь 3- В нужном пакете в каталоге test вам нужно создать класс Java (я предлагаю использовать Test.java). введите описание изображения здесь 4- В созданном классе введите «@Test». Затем, среди опций, которые вам предоставляет IntelliJ, выберите Добавить 'JUnitx' в путь к классам. 5- Напишите ваш тестовый метод в вашем тестовом классе. Подпись метода выглядит так:введите описание изображения здесь введите описание изображения здесь

@Test
public void test<name of original method>(){
...
}

Вы можете сделать свои утверждения, как показано ниже:

Assertions.assertTrue(f.flipEquiv(node1_1, node2_1));

Это импорт, который я добавил:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

введите описание изображения здесь

Это тест, который я написал: введите описание изображения здесь

Вы можете проверить свои методы, как показано ниже:

Assertions.assertEquals(<Expected>,<actual>);
Assertions.assertTrue(<actual>);
...

Для запуска модульных тестов щелкните правой кнопкой мыши тест и выберите «Выполнить». введите описание изображения здесь

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

Я надеюсь, что это помогает. Вы можете увидеть структуру проекта в GitHub https://github.com/m-vahidalizadeh/problem_solving_project .


12
Любите ваш ответ, это лучшее "как"!
алиса

4
Я рад, что мой ответ был полезным. Спасибо за ваш комментарий.
Мохаммед

1
Вот как должны выглядеть уроки; чистый, лаконичный, полный пример. Очень хорошо.
Jack of Blades

1
Большое спасибо, Джек. Я рад, что вы нашли это полезным.
Мухаммед

18

Это очень общий вопрос, и есть много способов, на которые можно ответить.

Если вы хотите использовать JUnit для создания тестов, вам нужно создать свой класс testcase, а затем создать отдельные методы тестирования, которые тестируют определенную функциональность тестируемого класса / модуля (классы с одним тестовым сценарием обычно связаны с одним «производственным» классом, который проверяется) и внутри этих методов выполняют различные операции и сравнивают результаты с тем, что было бы правильно. Особенно важно постараться охватить как можно больше угловых случаев.

В вашем конкретном примере вы можете, например, проверить следующее:

  1. Простое сложение между двумя положительными числами. Добавьте их, а затем убедитесь, что результат соответствует ожиданиям.
  2. Добавление между положительным и отрицательным числом (которое возвращает результат со знаком первого аргумента).
  3. Добавление между положительным и отрицательным числом (которое возвращает результат со знаком второго аргумента).
  4. Сложение между двумя отрицательными числами.
  5. Дополнение, которое приводит к переполнению.

Чтобы проверить результаты, вы можете использовать различные методы assertXXX из класса org.junit.Assert (для удобства вы можете сделать 'import static org.junit.Assert. *'). Эти методы проверяют определенное условие и проваливают тест, если оно не проверяется (с определенным сообщением, необязательно).

Пример класса testcase в вашем случае (без определения содержимого методов):

import static org.junit.Assert.*;

public class AdditionTests {
    @Test
    public void testSimpleAddition() { ... }


    @Test
    public void testPositiveNegativeAddition() { ... }


    @Test
    public void testNegativePositiveAddition() { ... }


    @Test
    public void testNegativeAddition() { ... }


    @Test
    public void testOverflow() { ... }
}

Если вы не привыкли писать модульные тесты, а вместо этого тестируете свой код, создавая специальные тесты, которые затем проверяются «визуально» (например, вы пишете простой метод main, который принимает аргументы, введенные с помощью клавиатуры, а затем распечатывает результаты - и затем вы продолжаете вводить значения и проверять себя, если результаты верны), тогда вы можете начать с написания таких тестов в указанном формате и проверки результатов с помощью правильного метода assertXXX вместо того, чтобы делать это вручную. Таким образом, вы можете перезапустить тест намного проще, чем если бы вам приходилось делать ручные тесты.


8

Как упомянуто @CoolBeans, взгляните на jUnit . Вот краткое руководство, которое поможет вам начать работу с jUnit 4.x

Наконец, если вы действительно хотите больше узнать о тестировании и разработке через тестирование (TDD), я рекомендую вам взглянуть на следующую книгу Кента Бека: Разработка через тестирование на примере .


6

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

  • Тестирование (всевозможных вещей) сравнивает фактическое поведение чего-либо (тестируемая система, SUT) с ожидаемым поведением.

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

  • То, что программа или часть программы (класс или метод) должны делать, это их спецификация . Поэтому для тестирования программного обеспечения требуется наличие спецификации для SUT. Это может быть явное описание или неявная спецификация того, что ожидается.

  • Поэтому автоматическое модульное тестирование требует точной и однозначной спецификации класса или метода, который вы тестируете.

  • Но вам нужна была эта спецификация, когда вы решили написать этот код. Таким образом, часть того, о чем идет речь, фактически начинается, прежде чем вы напишете хотя бы одну строку SUT. Техника тестирования Test Driven Development (TDD) доводит эту идею до крайности и заставляет вас создавать код модульного тестирования, прежде чем писать код для тестирования.

  • Фреймворки модульного тестирования проверяют ваше SUT, используя утверждения . Утверждение - это логическое выражение (выражение с booleanтипом результата; предикат ), которое должно быть, trueесли SUT ведет себя правильно. Поэтому спецификация должна быть выражена (или повторно выражена) как утверждения.

  • Полезной техникой для выражения спецификации в качестве утверждений является программирование по контракту . Эти спецификации в терминах постусловий . Постусловие - это утверждение о публично видимом состоянии SUT после возврата из метода или конструктора. Некоторые методы имеют постусловия, которые являются инвариантами , которые являются предикатами, которые являются истинными до и после выполнения метода. Класс также можно сказать , что есть инварианты, которые постусловия каждого конструктора и методы класса, и , следовательно , должна всегда быть правдой. Постусловия (и инварианты) выражаются только с точки зрения публичности видимого состояния: publicа protectedполя, значения которых возвращаются, возвращаютсяpublicи protectedметоды (такие как геттеры), а также общедоступное состояние объектов, переданных (посредством ссылки) в методы.


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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.