Хук выполнения до и после Suite в jUnit 4.x

Я пытаюсь выполнить предварительную настройку и разборку для набора интеграционных тестов, используя jUnit 4.4 для выполнения тестов. Разборка должна выполняться надежно. У меня есть другие проблемы с TestNG, поэтому я хочу вернуться к jUnit. Какие хуки доступны для выполнения перед запуском любых тестов и после завершения всех тестов?

Примечание: мы используем maven 2 для нашей сборки. Я пробовал использовать фазы maven pre- и post-integration-test, но, если тест не прошел, maven останавливается и не запускает post-integration-test, что не помогает.

Для интеграционных тестов вы должны использовать maven-failsafe-plugin вместо surefire. Это не пропустит post-integration-test, если тест не пройден. См. Также эта страница вики.

Chris H. 23.12.2013 20:27

не могли бы вы поделиться своей окончательной реализацией?

vikramvi 05.09.2018 15:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
84
2
100 457
11

Ответы 11

Насколько мне известно, в JUnit нет механизма для этого, однако вы можете попробовать создать подкласс Suite и переопределить метод run () версией, которая предоставляет хуки.

Используя аннотации, вы можете сделать что-то вроде этого:

import org.junit.*;
import static org.junit.Assert.*;
import java.util.*;

class SomethingUnitTest {
    @BeforeClass
    public static void runBeforeClass()
    {

    }

    @AfterClass
    public static void runAfterClass()
    {  

    }

    @Before  
    public void setUp()
    {

    }

    @After
    public void tearDown()
    {

    }

    @Test
    public void testSomethingOrOther()
    {

    }

}

Настройку и разборку необходимо выполнять один раз за запуск. Это поможет, только если все тесты будут в одном классе.

sblundy 17.09.2008 17:35

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

Ben 01.01.2021 02:37

Тогда я думаю, что единственный способ получить нужную вам функциональность - это сделать что-то вроде

import junit.framework.Test;  
import junit.framework.TestResult;  
import junit.framework.TestSuite;  

public class AllTests {  
    public static Test suite() {  
        TestSuite suite = new TestSuite("TestEverything");  
        //$JUnit-BEGIN$  
        suite.addTestSuite(TestOne.class);  
        suite.addTestSuite(TestTwo.class);  
        suite.addTestSuite(TestThree.class);  
        //$JUnit-END$  
     }  

     public static void main(String[] args)  
     {  
        AllTests test = new AllTests();  
        Test testCase = test.suite();  
        TestResult result = new TestResult();  
        setUp();  
        testCase.run(result);  
        tearDown();  
     }  
     public void setUp() {}  
     public void tearDown() {}  
} 

Я использую что-то подобное в eclipse, поэтому я не уверен, насколько он переносим за пределами этой среды

Это пример для JUnit3, и OP запросил JUnit4, но на всякий случай некоторые пользователи JUnit3 найдут этот вопрос ... Для JUnit3 было бы лучше избавиться от метода main () и использовать метод suite () оберните TestSuite в подкласс junit.extensions.TestSetup. У вас все еще есть те же предостережения, что и в примере Джули, о запуске отдельных тестовых классов в вашей среде IDE.

NamshubWriter 05.11.2010 17:55

Да, можно надежно запускать методы установки и удаления до и после любых тестов в наборе тестов. Позвольте мне продемонстрировать в коде:

package com.test;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {

    @BeforeClass
    public static void setUp() {
        System.out.println("setting up");
    }

    @AfterClass
    public static void tearDown() {
        System.out.println("tearing down");
    }

}

Итак, ваш класс Test1 будет выглядеть примерно так:

package com.test;

import org.junit.Test;


public class Test1 {
    @Test
    public void test1() {
        System.out.println("test1");
    }

}

... и вы можете представить, что Test2 похож. Если вы запустите TestSuite, вы получите:

setting up
test1
test2
tearing down

Таким образом, вы можете видеть, что установка / удаление выполняется только до и после всех тестов соответственно.

Уловка: это работает, только если вы запускаете набор тестов, а не тестируете Test1 и Test2 как отдельные тесты JUnit. Вы упомянули, что используете maven, а плагин maven surefire любит запускать тесты индивидуально, а не как часть пакета. В этом случае я бы рекомендовал создать суперкласс, который расширяет каждый тестовый класс. Затем суперкласс содержит аннотированные методы @BeforeClass и @AfterClass. Хотя это не так чисто, как описанный выше метод, я думаю, что он вам подойдет.

Что касается проблемы с неудачными тестами, вы можете установить maven.test.error.ignore, чтобы сборка продолжалась на неудачных тестах. Это не рекомендуется как постоянная практика, но она должна помочь вам работать до тех пор, пока все ваши тесты не пройдут. Подробнее см. документация maven surefire.

Это отлично сработало для меня, когда я вошел в maven-surefire-plugin и создал список включений, указывающий на набор, который я хотел запустить.

Jherico 19.11.2009 09:10

Начиная с JUnit 4.8.2, это не очень хорошо работает с параметризованными тестами. Методы @BeforeClass Suite будут запускаться после как метод @ Parameterized.Parameters теста, предотвращая любую зависимость от настройки Suite.

Anm 23.04.2011 22:39

В ответ на мой ответ при использовании @Theories вызов метода @DataPoints - это вызов после @BeforeClass из Suite.

Anm 24.04.2011 01:59

Извините за некро, но добавление BeforeClass / AfterClass к суперклассу не работает должным образом - они по-прежнему вызываются после завершения каждого тестового класса. Это для потомков.

Subu Sankara Subramanian 25.04.2012 08:30

Это все еще актуальный подход? Как избежать необходимости перечислять список тестовых классов в аннотации SuiteClasses?

Burhan Ali 05.10.2012 21:12

@SubuSankaraSubramanian см. Этот ответ: stackoverflow.com/a/28606190/363573

Stephan 18.05.2018 13:06

Мы тут

  • обновлен до JUnit 4.5,
  • написал аннотации, чтобы пометить каждый тестовый класс или метод, которым нужен рабочий сервис,
  • написал обработчики для каждой аннотации, которые содержали статические методы для реализации настройки и разрыва службы,
  • расширил обычный Runner, чтобы найти аннотации к тестам, добавив методы статического обработчика в цепочку выполнения теста в соответствующих точках.

Поскольку maven-surefire-plugin не запускает сначала класс Suite, а обрабатывает классы набора и тестирования одинаково, поэтому мы можем настроить плагин, как показано ниже, чтобы включить только классы набора и отключить все тесты. Suite выполнит все тесты.

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <includes>
                    <include>**/*Suite.java</include>
                </includes>
                <excludes>
                    <exclude>**/*Test.java</exclude>
                    <exclude>**/*Tests.java</exclude>
                </excludes>
            </configuration>
        </plugin>

Что касается "Примечание: мы используем maven 2 для нашей сборки. Я пробовал использовать этапы тестирования maven до и после интеграции, но, если тест не проходит, maven останавливается и не запускает тест после интеграции. , что бесполезно ".

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

Да, отказоустойчивый плагин позволит вам указать конкретную настройку и удаление. Хотя я не думаю, что отказоустойчивость существовала на момент публикации этого вопроса.

Jason Axelson 24.04.2012 07:01

При условии, что все ваши тесты могут расширять «технический» класс и находятся в одном пакете, вы можете сделать небольшой трюк:

public class AbstractTest {
  private static int nbTests = listClassesIn(<package>).size();
  private static int curTest = 0;

  @BeforeClass
  public static void incCurTest() { curTest++; }

  @AfterClass
  public static void closeTestSuite() {
      if (curTest == nbTests) { /*cleaning*/ }             
  }
}

public class Test1 extends AbstractTest {
   @Test
   public void check() {}
}
public class Test2 extends AbstractTest {
   @Test
   public void check() {}
}

Имейте в виду, что у этого решения много недостатков:

  • должен выполнить все тесты пакета
  • должен быть подклассом класса "techincal"
  • вы не можете использовать @BeforeClass и @AfterClass внутри подклассов
  • если вы выполняете только один тест в пакете, очистка не производится
  • ...

Для информации: listClassesIn () => Как найти все подклассы данного класса в Java?

Это не так, как показывают мои собственные тесты. У меня есть суперкласс, который запускает встроенную стеклянную рыбку на beforeclass и выключает ее после урока. У меня есть 2 класса, которые расширяют этот суперкласс. Класс before выполняется перед запуском тестов, определенных в каждом классе.

Jonathan Morales Vélez 21.11.2013 02:43

Мой коллега предложил следующее: вы можете использовать собственный RunListener и реализовать метод testRunFinished (): http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html#testRunFinished(org.junit.runner.Result)

Чтобы зарегистрировать RunListener, просто настройте плагин surefire следующим образом: http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html раздел «Использование кастомных слушателей и репортеров»

Эта конфигурация также должна выбираться отказоустойчивым плагином. Это отличное решение, потому что вам не нужно указывать наборы, поисковые тестовые классы или что-то еще - оно позволяет Maven творить чудеса, ожидая завершения всех тестов.

+1 Это первое пригодное для использования решение, которое я видел без громоздкого обслуживания класса Suites!

Stefan Haberl 24.06.2013 17:23

Если вы не хотите создавать набор и должны перечислять все свои тестовые классы, вы можете использовать отражение, чтобы найти количество тестовых классов динамически, и обратный отсчет в базовом классе @AfterClass, чтобы выполнить tearDown только один раз:

public class BaseTestClass
{
    private static int testClassToRun = 0;

    // Counting the classes to run so that we can do the tear down only once
    static {
        try {
            Field field = ClassLoader.class.getDeclaredField("classes");
            field.setAccessible(true);

            @SuppressWarnings({ "unchecked", "rawtypes" })
            Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
            for (Class<?> clazz : classes) {
                if (clazz.getName().endsWith("Test")) {
                    testClassToRun++;
                }
            }
        } catch (Exception ignore) {
        }
    }

    // Setup that needs to be done only once
    static {
        // one time set up
    }

    @AfterClass
    public static void baseTearDown() throws Exception
    {
        if (--testClassToRun == 0) {
            // one time clean up
        }
    }
}

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

Теперь все, что вам нужно сделать, это расширить этот класс для всех ваших тестовых классов. У нас уже был базовый класс, обеспечивающий некоторые общие вещи для всех наших тестов, так что это было лучшее решение для нас.

Вдохновение исходит из этого SO-ответа https://stackoverflow.com/a/37488620/5930242

Если вы не хотите расширять этот класс повсюду, этот последний ответ SO может сделать то, что вы хотите.

Другие вопросы по теме