Запуск приложения до и после Suite в jUnit 4.x
Я пытаюсь выполнить предварительную настройку и отключение для набора интеграционных тестов, используя jUnit 4.4 для выполнения тестов. Срыв должен выполняться надежно. У меня другие проблемы с TestNG, поэтому я ищу порт для jUnit. Какие крючки доступны для выполнения до запуска любых тестов и после завершения всех тестов?
Примечание. Мы используем maven 2 для нашей сборки. Я пробовал использовать фазы maven pre-
и post-integration-test
, но если тест завершился неудачно, maven останавливается и не запускает post-integration-test
, что не помогает.
Ответы
Ответ 1
Да, можно надежно запускать методы настройки и сбрасывания до и после любых тестов в наборе тестов. Позвольте мне продемонстрировать код:
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.
Ответ 2
Один из моих коллег предложил следующее: вы можете использовать собственный 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 делать свою магию, ожидая завершения всех тестов.
Ответ 3
Вы можете использовать @аннотацию ClassRule в JUnit 4.9+ как Я описал в ответе другой вопрос.
Ответ 4
Используя аннотации, вы можете сделать что-то вроде этого:
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()
{
}
}
Ответ 5
Здесь мы
- обновлен до JUnit 4.5,
- написал аннотации, чтобы пометить каждый тестовый класс или метод, которым нужна рабочая служба,
- написал обработчики для каждой аннотации, содержащие статические методы для реализации настройки и удаления службы,
- расширил обычный Runner, чтобы найти аннотации на тестах, добавив методы статического обработчика в цепочку выполнения теста в соответствующих точках.
Ответ 6
При условии, что все ваши тесты могут расширить "технический" класс и находиться в одном пакете, вы можете сделать небольшой трюк:
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?
Ответ 7
Что касается "Примечание: мы используем maven 2 для нашей сборки. Я пробовал использовать фазы pre-and post-integration-test maven, но, если тест завершился неудачно, maven останавливается и не запускает пост- интеграция-тест, который не помогает".
вместо этого вы можете попробовать защищенный плагин, я думаю, что у него есть возможность обеспечить очистку независимо от настройки или состояния промежуточной стадии
Ответ 8
Единственный способ, по которому я думаю, получить необходимую функциональность, - это сделать что-то вроде
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, поэтому я не уверен, насколько он переносится вне этой среды
Ответ 9
Насколько я знаю, в JUnit нет механизма для этого, однако вы можете попробовать подклассифицировать Suite и переопределить метод run() версией, которая обеспечивает привязки.
Ответ 10
Так как maven-surefire-plugin не запускает класс класса сначала, но рассматривает классы классов и тестов одинаково, поэтому мы можем настроить плагин, как показано ниже, чтобы включить только классы классов и отключить все тесты. 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>
Ответ 11
Если вы не хотите создавать набор и должны перечислять все свои тестовые классы, вы можете использовать рефлексию для динамического поиска количества тестовых классов и обратного отсчета в базовом классе @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 fooobar.com/info/75792/...
Если вы не хотите распространять этот класс повсюду, этот последний ответ SO может делать то, что вы хотите.