2008-09-17 8 views
74

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

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

+1

Для тестов интеграции вы должны использовать [maven-отказоустойчивый плагин] (http://maven.apache.org/surefire/maven-failsafe-plugin/) вместо surefire. Это не пропустит «пост-интеграцию-тест», если тест завершился неудачно. См. Также [эта страница вики] (http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing). – 2013-12-23 16:27:47

ответ

0

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

+0

Возможно ли это в maven? – sblundy 2008-09-17 13:31:01

7

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

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() 
    { 

    } 

} 
+2

Установка и отключение должны выполняться один раз за каждый запуск. Это поможет только в том случае, если все тесты находятся в одном классе. – sblundy 2008-09-17 13:35:16

1

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

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, поэтому я не уверен, насколько портативен он за пределами этой среды.

+2

Это пример для JUnit3, и OP запросил JUnit4, но на всякий случай некоторые пользователи JUnit3 найдут этот вопрос ... Для JUnit3 было бы лучше избавиться от метода main() и иметь набор() метод оберните TestSuite в подкласс junit.extensions.TestSetup. У вас все еще есть те же оговорки, что и пример Джулии о запуске отдельных тестовых классов в вашей среде IDE. – NamshubWriter 2010-11-05 14:55:05

103

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

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 documentation.

+1

Это сработало отлично для меня, как только я зашел в плагин maven-surefire и создал список включений, указывающий на набор, который я хотел запустить. – Jherico 2009-11-19 06:10:32

+0

Начиная с JUnit 4.8.2, это не очень хорошо работает с параметризованными тестами. Методы @BeforeClass Suite будут запущены _after_ методом @ Parameterized.Parameters теста, предотвращая любую зависимость от настройки Suite. – Anm 2011-04-23 18:39:03

+0

В ответ на меня, при использовании @ Theories, вызов метода @DataPoints является вызовом _after_ @BeforeClass Suite. – Anm 2011-04-23 21:59:07

3

Здесь мы

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

Поскольку 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> 
2

Что касается «Примечание: мы используем Maven 2 для нашей сборки я попытался с помощью предварительных & после интеграционного тестирования фазы Maven, но, если тест не пройден, специалист останавливается и Безразлично». t запустить пост-интеграцию-тест, который не помогает ».

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

3

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

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() =>How do you find all subclasses of a given class in Java?

28

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

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

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

0

Если вы не хотите создавать набор и должны перечислять все свои тестовые классы, вы можете использовать отражение, чтобы динамически найти количество тестовых классов и обратный отсчет в базовом классе @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 ответ мог бы сделать то, что вы хотите.