2016-05-27 5 views
0

В IntelEI и Eclipse IDE (и, возможно, некоторые другие) также можно запускать все тестовые классы из пакета (или даже всех тестовых классов в проекте) без необходимости поместить каждую из них явно в класс тестового набора (this - это то, чего я хочу избежать). Просто щелкните правой кнопкой мыши -> запустите все тесты и вуаля!Очистка после всех тестов JUnit без объявления классов классов тестов

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

Сначала я попытался использовать RunListener и его метод testRunFinished(), но он вызывается после каждого атомного теста, поэтому не то, что я хочу, когда запускаю многие из них.

Тогда я подумал о финализаторах и runFinalizersOnExit(true), к сожалению, он устарел и работал только на одном из компьютеров, на которых выполняются тесты.

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

import org.junit.Test; 

public class Main { 
    static { 
     System.out.println("In a static block!"); 

     new Thread(new Runnable() { 
      public void run() { 
       System.out.println("Starting static thread!"); 

       try { 
        while (true) { 
         Thread.sleep(1000); 
         System.out.println("Static thread working..."); 
        } 
       } catch (InterruptedException e) { 
        System.err.println("Static thread interrupted!"); 
        e.printStackTrace(); 
       } catch (Exception e) { 
        System.err.println("Static thread catches exception!"); 
        e.printStackTrace(); 
       } finally { 
        System.err.println("Static thread in finally method."); 
        Thread.currentThread().interrupt(); 
       } 

      } 
     }).start(); 

     System.out.println("Exiting static block!"); 
    } 

    @Test 
    public void test() throws Exception { 
     System.out.println("Running test!"); 
     Thread.sleep(3000); 
     System.out.println("Stopping test!"); 
    } 
} 

Не повезло. Нить убивается после завершения теста. И даже finally блока никогда не выполняется ...

In a static block! 
Exiting static block! 
Running test! 
Starting static thread! 
Static thread working... 
Static thread working... 
Stopping test! 
Static thread working... 

Желаемое поведение было бы:

  1. правой кнопки мыши
  2. запустить все тесты
  3. TestA работает под управлением ...
  4. TestA сделано
  5. TestB работает ...
  6. TestB done
  7. ... подробнее тестовые классы ...
  8. очистки

ответ

1

Я нашел решение моей проблемы. Мой коллега предложил «эй, разве ты не можешь просто рассчитать тестовые классы?» - и это то, что я сделал.

Немного отражения магии здесь используется, так что код не может быть переносимым:

public abstract class CleaningTestRunner extends BlockJUnit4ClassRunner { 
    protected abstract void cleanupAfterAllTestRuns(); 

    private static long TEST_CLASSES_AMOUNT; 
    private static long TEST_RUNS_FINISHED = 0; 
    private static boolean CLASSES_COUNTED = false; 

    static { 
     while (!CLASSES_COUNTED) { 
      try { 
       Field f = ClassLoader.class.getDeclaredField("classes"); 
       f.setAccessible(true); 

       Vector<Class> classes = (Vector<Class>) f.get(CleaningTestRunner.class.getClassLoader()); 
       TEST_CLASSES_AMOUNT = 0; 
       for (Class<?> klass : classes) { 
        if (klass.isAnnotationPresent(RunWith.class)) { 
         if (CleaningTestRunner.class.isAssignableFrom(klass.getAnnotation(RunWith.class).value())) { 
          for (Method method : klass.getMethods()) { 
           if (method.isAnnotationPresent(Test.class)) { 
            ++TEST_CLASSES_AMOUNT; 
            break; 
           } 
          } 
         } 
        } 

       } 

       CLASSES_COUNTED = true; 
      } catch (Exception ignored) { 

      } 
     } 
    } 

    public CleaningTestRunner(Class<?> klass) throws InitializationError { 
     super(klass); 
    } 

    @Override 
    public void run(RunNotifier notifier) { 
     notifier.addListener(new TestCleanupListener()); 
     super.run(notifier); 
    } 

    private class TestCleanupListener extends RunListener { 
     @Override 
     public void testRunFinished(Result result) throws Exception { 
      ++TEST_RUNS_FINISHED; 

      if (TEST_RUNS_FINISHED == TEST_CLASSES_AMOUNT) { 
       cleanupAfterAllTestRuns(); 
      } 
     } 
    } 
} 
1

Не уверен, что если я полностью иметь свой вопрос прямо, но я думаю, что вы хотите, прежде, beforeClass, после того, как и методы afterClass. т.е.

@BeforeClass 
public void beforeClass() { 
    // Do stuff before test class is run 
} 

@Before 
public void before() { 
    // Do stuff before each test is run 
} 

@After 
public void after() { 
    // DO stuff after each test is run 
} 

@AfterClass 
public void afterClass() { 
    // DO stuff after test class is run 
} 

Вы можете делать вещи на более глобальном уровне с помощью некоторых хакеров или других фреймворков. Например, тестовые комплекты Spring. Но я постараюсь сохранить такие вещи в рамках одного тестового класса.

+0

Нет, он по-прежнему выполняется [после одного тестового класса] (http://junit.sourceforge.net/ javadoc/org/junit/AfterClass.html), а не после того, как все сделано. Я запускаю тесты в нескольких тестовых классах. – Jezor

+0

Хорошо. Затем вам нужно начать возиться с наборами или посмотреть на использование других фреймворков, которые могут справиться с этим. Но мне интересно, может быть, лучший подход может состоять в том, чтобы реорганизовать тесты, чтобы очистка могла быть выполнена после каждого тестового класса.Возможно, вы пытаетесь работать в слишком больших масштабах. – drekka

+0

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

Смежные вопросы