JUnit путаница: использовать «extends TestCase» или «@Test»?

Для этого вам нужно __new__(). (И вам также нужно сделать его классом нового стиля, предполагая, что вы используете Python 2, путем подкласса object.)

class ClassA(object):
    def __new__(cls,theirnumber):
        if theirnumber > 10:
            # all big numbers should be ClassB objects:
            return ClassB.ClassB(theirnumber)
        else:
            # numbers under 10 are ok in ClassA.
            return super(ClassA, cls).__new__(cls, theirnumber)

__new__() выполняется как часть процесса создания класса до __init__(). В основном __new__() - это то, что на самом деле создает новый экземпляр, а затем __init__() вызывается для инициализации его свойств. Вот почему вы можете использовать __new__(), но не __init__(), чтобы изменить тип созданного объекта: после запуска __init__() объект уже создан, и слишком поздно менять его тип. (Ну ... не совсем, но это попадает в очень загадочную черную магию Python.) См. документацию .

В этом случае, однако, я бы сказал, что фабричная функция более вероятно, что-то вроде

def thingy(theirnumber):
    if theirnumber > 10:
        return ClassB.ClassB(theirnumber)
    else:
        return ClassA.ClassA(theirnumber)

. Кстати, обратите внимание, что если вы сделаете то, что я сделал с __new__() выше, если возвращен ClassB, метод __init__() в ClassB будет вызываться not ! Python только вызывает __init__(), если объект, возвращенный из __new__(), является экземпляром класса, в котором содержится метод __new__() (здесь ClassA). Это еще один аргумент в пользу подхода фабричной функции.

144
задан Community 23 May 2017 в 12:34
поделиться

5 ответов

Отличить довольно просто:

  • расширение TestCase - это способ написания модульных тестов в JUnit 3 (конечно, он все еще поддерживается в JUnit 4)
  • с использованием аннотации @Test - это способ, представленный JUnit 4

. Обычно вам следует выбирать путь аннотации, если только не совместим с JUnit 3 (и / или более ранней версией Java чем Java 5). Новый способ имеет несколько преимуществ:

  • Аннотация @Test более явная и ее легче поддерживать в инструментах (например, таким способом легко искать все тесты)
  • Множественный методы могут быть аннотированы @Before / @BeforeClass и @After / @AfterClass , обеспечивая большую гибкость
  • Поддержка ] @Rule аннотации для таких вещей, как ExpectedException
  • Поддержка аннотации @Ignored
  • Поддержка альтернативных исполнителей тестов, использующих @RunWith

To проверьте ожидаемые исключения в JUnit 3 TestCase , вам придется сделать текст явным.

public void testMyException() {
  try {
    objectUnderTest.myMethod(EVIL_ARGUMENT);
    fail("myMethod did not throw an Exception!");
  } catch (MyException e) {
    // ok!
    // check for properties of exception here, if desired
  }
}

JUnit 5 представил еще одно изменение API, но по-прежнему использует аннотации. Новая аннотация @Test - org.junit.jupiter.api.Test («старая» аннотация JUnit 4 была org.junit.Test ), но он работает почти так же, как JUnit 4.

114
ответ дан 23 November 2019 в 22:32
поделиться
  1. "Предпочтительным" подходом было бы использование аннотаций, которые были введены после Junit 4. Они упрощают многие вещи (см. Ваш второй вопрос)

  2. Вы можете использовать для этого простой блок try / catch:


public void testForException() {
    try {
        Integer.parseInt("just a string");
        fail("Exception should have been thrown");
    } catch (final Exception e) {
        // expected
    }
}
1
ответ дан 23 November 2019 в 22:32
поделиться

В вашем вопросе есть часть без ответа, а именно: «Как правильно группировать тесты для подхода B?»

Официальный ответ заключается в том, что вы аннотируете класс с помощью @RunWith (Suite.class) а затем используйте аннотацию @ Suite.SuiteClasses, чтобы перечислить классы. Вот как это делают разработчики JUnit (вручную перечисляя каждый класс в наборе). Во многих отношениях этот подход является улучшением, поскольку он тривиален и интуитивно понятен для добавления поведения перед набором и после набора (просто добавьте метод @BeforeClass и @AfterClass к классу, аннотированному с помощью @RunWith - намного лучше, чем старый TestFixture ).

Однако у него есть шаг назад, поскольку аннотации не позволяют динамически создавать список классов, и работа над этой проблемой становится немного некрасивой. Вы должны создать подкласс класса Suite и динамически создать массив классов в подклассе и передать его конструктору Suite, но это неполное решение, поскольку другие подклассы Suite (например, категории) не работают с ним и по существу не поддерживают динамическую коллекцию классов Test.

15
ответ дан 23 November 2019 в 22:32
поделиться

Я предпочитаю JUnit 4 (аннотационный подход), потому что считаю его более гибким.

Если вы хотите создать набор тестов в JUnit 4, вы должны создать класс, группирующий все тесты следующим образом:

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


@RunWith(Suite.class)
@SuiteClasses({
    Test1.class,
    Test2.class,
    Test3.class,
    Test4.class
})public class TestSuite
{
 /* empty class */
}
24
ответ дан 23 November 2019 в 22:32
поделиться

Вам следует использовать JUnit 4. Так лучше.

Многие платформы перестали рекомендовать поддержку JUnit 3.8.

Это из справочной документации Spring 3.0:

[Предупреждение] Устаревшая иерархия классов JUnit 3.8 deprecated

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

4
ответ дан 23 November 2019 в 22:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: