Skip to content

Instantly share code, notes, and snippets.

@vchernogorov
Last active February 3, 2023 18:37
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save vchernogorov/28411d1ca9ad476a850af6762ea2a4d1 to your computer and use it in GitHub Desktop.
Save vchernogorov/28411d1ca9ad476a850af6762ea2a4d1 to your computer and use it in GitHub Desktop.
JUnit 4

JUnit 4

Данный гист содержит информацию об основных аспектах использования фреймворка для юнит тестирования JUnit 4.

Содержание:

Аннотации

  1. @Test - любые тесты должны быть помечены этой аннотацией.

    • С помощью данной аннотации не нужно наследоваться от TestCase класса.
    • Параметры:
      • expected - указывает тип исключения, которое должно быть брошено из данного теста. Например @Test(expected = IndexOutOfBoundsException.class).
      • timeout - указывает время в миллисекундах, после истечения которого тест помечается как непройденный. Например @Test(timeout = 100).
    • Пример:
    @Test
    public void addition() {
        assertEquals(12, simpleMath.add(7, 5));
    }
  2. @Before - аннотация позволяет выполнять логику перед выполнением каждого теста.

    • Пример:
    @Before
    public void runBeforeEveryTest() {
        simpleMath = new SimpleMath();
    }
  3. @After - аннотация позволяет выполнять логику после выполнения каждого теста.

    • Пример:
    @After
    public void runAfterEveryTest() {
        simpleMath = null;
    }
  4. @BeforeClass - аннотация позволяет выполнять логику перед выполнением всех тестов в данном классе.

    • Пример:
    @BeforeClass
    public static void runBeforeClass() {
        // run for one time before all test cases
    }
  5. @AfterClass - аннотация позволяет выполнять логику после выполнения всех тестов в данном классе.

    • Пример:
    @AfterClass
    public static void runAfterClass() {
        // run for one time after all test cases
    }
  6. @Ignore - тест, помеченный данной аннотацией, будет пропускаться.

    • Параметры:
      • Параметром служит строка - причина пропуска теста.
    • Пример:
    @Ignore(“Not Ready to Run”)
    @Test
    public void multiplication() {
        assertEquals(15, simpleMath.multiply(3, 5));
    }
  7. @RunWith - если класс содержит данную аннотацию, JUnit будет запускать тесты в классе, который указан в параметрах этой аннотации, вместо стандартного раннера, встроенного в JUnit.

    • Стандартный класс раннера - BlockJUnit4ClassRunner, который заменяет старый класс - JUnit4ClassRunner.
    • Разновидность раннеров:
      • Suite - позволяет вручную составить набор из тестов разных классов.
      • Parameterized - реализует параметризованные тесты.
      • Categories - включает подвид тестов, принадлежащих той или иной категории.
      • Enclosed - запуская класс с этой аннотацией, можно будет запускать тесты из внутренних классов.
    • Пример:
    @RunWith(Suite.class)
    @SuiteClasses({ATest.class, BTest.class, CTest.class})
        public class ABCSuite {
    }
  8. @Suite.SuiteClasses - с помощью данной аннотации, тестовый класс совмещает в себе другие тестовые классы, указанные в параметрах.

    • Пример:
    @RunWith(Suite.class)
    @SuiteClasses({ATest.class, BTest.class, CTest.class})
        public class ABCSuite {
    }
  9. @Parameterized.Parameters - статический метод, содержащий данную аннотацию создает и возвращает коллекцию из массивов элементов, которые являются параметрами для тестового метода.

    • Также можно повесить аннотацию @Parameter на public поле, чтобы сразу инжектить значения, вместо того, чтобы передавать их через конструктор. Параметр value - указывает значение по дефолту для поля, на котором висит эта аннотация.
    • Параметры:
      • name - изменяет имя параметризованного теста. Допускается использование таких плейсхолдоров, как {index}, {0}, {1} и так далее.
    • Пример:
    @RunWith(Parameterized.class)
    public class FibonacciTest {
        @Parameters(name = "{index}: fib({0})={1}")
        public static Iterable<Object[]> data() {
            return Arrays.asList(new Object[][] {
                    { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 }
            });
        }
        @Parameter // first data value (0) is default
        public /* NOT private */ int fInput;
        @Parameter(value = 1)
        public /* NOT private */ int fExpected;
        @Test
        public void test() {
            assertEquals(fExpected, Fibonacci.compute(fInput));
        }
    }
  10. @Category - разновидность раннера, который запускает только те тестовые классы и методы, которые аннотированы @IncludeCategory аннотацией или ее расширениями.

    • Категориями могут быть как классы, так и интерфейсы.
    • @IncludeCategory - включает указанную в параметрах категорию.
    • @ExcludeCategory - исключает указанную в параметрах категорию.
    • Пример:
    public interface FastTests { /* category marker */ }
    public interface SlowTests { /* category marker */ }
    public class A {
      @Test
      public void a() {}
      @Category(SlowTests.class)
      @Test
      public void b() {}
    }
    @Category({SlowTests.class, FastTests.class})
    public class B {
      @Test
      public void c() {}
    }
    @RunWith(Categories.class)
    @IncludeCategory(SlowTests.class)
    @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
    public class SlowTestSuite {
      // Will run A.b and B.c, but not A.a
    }
    @RunWith(Categories.class)
    @IncludeCategory(SlowTests.class)
    @ExcludeCategory(FastTests.class)
    @SuiteClasses( { A.class, B.class }) // Note that Categories is a kind of Suite
    public class SlowTestSuite {
      // Will run A.b, but not A.a or B.c
    }
  11. @Rule - с помощью этой аннотации можно создавать специальные объекты, которые используются в тестовых методах. Тестеры могут реиспользовать или расширять эти объекты или создавать свои.

    • Стандартные правила:
      • TemporaryFolder - позволяет создавать файлы или папки, которые удаляются по окончании работы метода. По дефолту не выбрасывается исключений, если ресурс не может быть удален.
      • ExternalResource - базовый класс, который устанавливает внешние ресурсы перед тестом, такие как: файлы, сокеты, сервера, соединения с базами данных и другие.
      • ErrorCollector - позволяет выполнять тест до конца, собирая всевозможные ошибки, которые встретятся во время его выполнения.
      • Verifier - ???.
      • TestWatcher - данное правило позволяет выполнять логику на определенных событиях теста (succeeded, failed, skipped, starting, finished), не изменяя сам тест. Например, этот класс может вести кастомные логи каждого пройденного или упавшего теста.
      • TestName - позволяет выводить название текущего тестового метода.
      • Timeout - устанавливает ограничение по времени выполнения на все методы в тестовом классе.
      • ExpectedException - позволяет вставлять в тесты ожидания исключений или сообщений.
      • RuleChain - устанавливает порядок правил.
      • ExpectedException - позволяет вставлять в тесты ожидания исключений или сообщений.
    • Пример:
    public class DigitalAssetManagerTest {
      @Rule
      public TemporaryFolder tempFolder = new TemporaryFolder();
      @Rule
      public ExpectedException exception = ExpectedException.none();
      @Test
      public void countsAssets() throws IOException {
        File icon = tempFolder.newFile("icon.png");
        File assets = tempFolder.newFolder("assets");
        createAssets(assets, 3);
        DigitalAssetManager dam = new DigitalAssetManager(icon, assets);
        assertEquals(3, dam.getAssetCount());
      }
      private void createAssets(File assets, int numberOfAssets) throws IOException {
        for (int index = 0; index < numberOfAssets; index++) {
          File asset = new File(assets, String.format("asset-%d.mpg", index));
          Assert.assertTrue("Asset couldn't be created.", asset.createNewFile());
        }
      }
      @Test
      public void throwsIllegalArgumentExceptionIfIconIsNull() {
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Icon is null, not a file, or doesn't exist.");
        new DigitalAssetManager(null, null);
      }
    }
  12. @FixMethodOrder - класс, помеченный данной аннотацией, сможет запускать тесты в некотором установленном порядке, так как изначально их порядок устанавливается через рефлексию.

    • Параметры:
      • Параметром является тип сортировки тестовых методов. Возможные типы: DEFAULT, JVM, NAME_ASCENDING.

Asserts & Assumes

  1. Assert — это конструкция, позволяющая проверять предположения о значениях произвольных данных в произвольном месте программы.

    • Пример:
    @Test
    public void testAssertEquals() {
      assertEquals("failure - strings are not equal", "text", "text");
    }
  2. Assume - это конструкция, позволяющая проверять корректность теста перед его выполнением.

    • По дефолту JUnit воспринимает тесты, которые не прошли какую-то assume проверку, как проигнорированные.
    • Упавший на assume проверке метод, помеченный аннотацией @Before пометит все тестовые методы в данном классе как проигнорированные.
    • Пример:
    @Test public void filenameIncludesUsername() {
        assumeThat(File.separatorChar, is('/'));
        assertThat(new User("optimus").configFileName(), is("configfiles/optimus.cfg"));
    }
  3. JUnit Asserts. JUnit предоставляет перегруженные ассерты для наиболее распространенных действий:

    • assertArrayEquals - проверяет два массива на равенство.
    • assertEquals - проверяет два примитива/объекта на равенство.
    • assertFalse - проверяет условие на ложность.
    • assertTrue - проверяет условие на истинность.
    • assertNotNull - проверяет, что объект не null.
    • assertNull - проверяет, что объект null.
    • assertNotSame - проверяет, что два объекта не ссылаются на одну область памяти.
    • assertSame - проверяет, что два объекта ссылаются на одну область памяти.
    • assertThat - специальный ассерт, исполользующий матчеры.
  4. assertThat - механизм ассертов, основанный на JMock 1. Преимущество нового метода в том, что он более читаем за счет матчеров, которые можно расширять.

    • Список матчеров из Hamcrest фреймворка, которые заменяют стандартные JUnit-овские ассерты:
      • anything - всегда удовлетворяет условию.
      • describedAs - пустышка, чтобы добавлять описание ошибки.
      • is - пустышка, чтобы улучшить читемость.
      • allOf - аналогия оператору "и".
      • anyOf - аналогия оператору "или".
      • not - аналогию оператору отрицания.
      • equalTo - проверка на равенство объектов, используя Object.equals.
      • hasToString - проверяет на равенство с помощью Object.toString.
      • instanceOf, isCompatibleType - проверка совпадения типов.
      • notNullValue, nullValue - проверка на null.
      • sameInstance - проверка инстансов объектов.
      • hasProperty - проверка JavaBeans пропертей.
      • array - позволяет устанавливать несколько матчеров.
      • hasEntry, hasKey, hasValue - проверка мапы на содержания ключа, значения или кортежа.
      • hasItem, hasItems - проверка коллекции на содержание элемента/ов.
      • hasItemInArray - проверка массива на содержание элемента.
      • closeTo - проверка чисел с плавающей запятой на близость по значению к заданному числу.
      • greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo - аналогия операторам неравенства.
      • equalToIgnoringCase - проверка на равенство строке, игнорируя регистр букв.
      • equalToIgnoringWhiteSpace - проверка равенство строке, игнорируя пробелы.
      • containsString, endsWith, startsWith - проверка на содержание вхождения строки.

Введение

  1. Юнит-тестирование или модульное тестирование - тип тестирования, при котором проверяется корректность отдельных модулей программы. Юнит-тесты пишутся для каждой нетривиальной функциональности.

    • Целью юнит-тестирования является изолированное тестирование отдельных частей программы, чтобы показать, что по отдельности эти части являются работоспособными.
  2. Интеграционное тестирование - тип тестирования, при котором отдельные программные модули объединяются и тестируются в группе. Обычно интеграционное тестирования проводится после модульного.

    • Целью интеграционного тестирования является проверка связей между компонентами, а также взаимодействия с различными частями системы.
  3. Системное тестирование - тип тестирования, при котором проверяются как функциональные, так и нефункциональные требования к системе в целом, используя окружение, максимально приближенное к тому, в котором она будет развернута.

    • Целью системного тестирования является выявление дефектов, связанных с использованием ресурсов системы, результатами ее работы, удобством использования и т.д.
  4. JUnit - фреймворк для юнит-тестирования Java кода.

    • Он является одним из семества xUnit фреймворков для различных языков программирования.
    • JUnit пропогандирует TDD.
  5. TDD (Test-Driven Development) - техника разработки, которая основывается на идее "сначала тестирование, потом кодинг". Подразумевается, что в первую очередь нужно написать тест для будущей функциональности, а затем саму функциональность. Такой подход увеличивает стабильность написанного кода и сводит к минимуму время, потраченное на отладку программы.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment