Лучшая практика: Инициализируйте поля класса JUnit в установке () или в объявлении?

Мне недавно потребовалось работать над приложением, которое включало анализ XML-документа, и я согласен с Джоном Галлоуэем в том, что подход на основе LINQ to XML, на мой взгляд, лучший. Мне все же пришлось немного подражать, чтобы найти полезные примеры, поэтому без лишних слов, вот несколько!

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

public void ParseXML(string filePath)  
{  
    // create document instance using XML file path
    XDocument doc = XDocument.Load(filePath);

    // get the namespace to that within of the XML (xmlns="...")
    XElement root = doc.Root;
    XNamespace ns = root.GetDefaultNamespace();

    // obtain a list of elements with specific tag
    IEnumerable<XElement> elements = from c in doc.Descendants(ns + "exampleTagName") select c;

    // obtain a single element with specific tag (first instance), useful if only expecting one instance of the tag in the target doc
    XElement element = (from c in doc.Descendants(ns + "exampleTagName" select c).First();

    // obtain an element from within an element, same as from doc
    XElement embeddedElement = (from c in element.Descendants(ns + "exampleEmbeddedTagName" select c).First();

    // obtain an attribute from an element
    XAttribute attribute = element.Attribute("exampleAttributeName");
}

С помощью этих функций я смог разобрать любой элемент и любой атрибут из файла XML без проблем!

112
задан Craig P. Motlin 4 February 2009 в 17:44
поделиться

6 ответов

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

, Когда примеры JUnit создают ArrayList в методе установки, они все продолжают тестировать поведение что ArrayList, со случаями как testIndexOutOfBoundException, testEmptyCollection, и т.п.. Перспектива там имеет кого-то пишущего, что класс и удостоверяющийся его работает правильно.

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

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

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

93
ответ дан Moss Collum 5 November 2019 в 09:38
поделиться

Я начал рыть меня, и я нашел одно потенциальное преимущество использования setUp(). Если какие-либо исключения будут выданы во время выполнения setUp(), то JUnit распечатает очень полезное отслеживание стека. С другой стороны, если исключение выдается во время объектной конструкции, в сообщении об ошибке просто говорится, что JUnit не мог инстанцировать тестового сценария, и Вы не видите номера строки, где отказ произошел, вероятно, потому что JUnit использует отражение для инстанцирования тестовых классов.

Ни одно из этого не относится к примеру создания пустого набора, так как это никогда не будет бросать, но это - преимущество setUp() метод.

42
ответ дан Craig P. Motlin 5 November 2019 в 09:38
поделиться

В дополнение к ответу B Alex.

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

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

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

жизненный цикл JUnits:

  1. Создают другой testclass экземпляр для каждого метода тестирования
  2. Повторение для каждого testclass экземпляра: установление вызова + называет testmethod

С некоторыми регистрациями в тесте с двумя методами тестирования, которые Вы получаете: (число является хэш-кодом)

  • Создающий новый экземпляр: 5718203
  • Создающий новый экземпляр: 5947506
  • Установка: 5718203
  • TestOne: 5718203
  • Установка: 5947506
  • TestTwo: 5947506
18
ответ дан Jurgen Hannaert 5 November 2019 в 09:38
поделиться

В Вашем случае (создающий список) на практике нет никакого различия. Но обычно лучше использовать установку (), потому что это поможет Junit сообщить об Исключениях правильно. Если исключение происходит в конструкторе/инициализаторе Теста, который является тестом отказ . Однако, если исключение происходит во время установки, естественно думать о нем как о некоторой проблеме в установке теста, и junit сообщает об этом соответственно.

6
ответ дан amit 5 November 2019 в 09:38
поделиться

Я предпочитаю удобочитаемость сначала, которая чаще всего не использует метод установки. Я делаю исключение, когда основная операция установки занимает много времени и повторяется в каждом тесте.
В той точке я перемещаюсь, та функциональность в метод установки с помощью @BeforeClass аннотация (оптимизируйте позже).

Пример оптимизации с помощью @BeforeClass метод установки: Я использую dbunit для некоторых функциональных испытаний базы данных. Метод установки ответственен за помещение базы данных в известном состоянии (очень медленный... 30 секунд - 2 минуты в зависимости от объема данных). Я загружаю эти данные в методе установки, аннотируемом @BeforeClass, и затем запускаю 10-20 тестов против того же набора данных в противоположность re-loading/initializing база данных в каждом тесте.

Используя Junit 3.8 (расширяющий TestCase как показано в Вашем примере) требует записи немного большего количества кода, чем просто добавление аннотации, но "выполненный однажды установка класса" все еще возможна.

5
ответ дан Alex B 5 November 2019 в 09:38
поделиться

Так как каждый тест выполняется независимо с новым экземпляром объекта, нет большого количества точки к Тестовому объекту, имеющему внутреннее состояние за исключением того, что общее между setUp() и отдельный тест и tearDown(). Это - одна причина (в дополнение к причинам, которые другие привели), что хорошо использовать setUp() метод.

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

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

В Вашем случае, где Вы просто создаете пустой список, я сделал бы тот же способ, которым Вы предлагаете: Присвойте новый список при объявлении. Особенно, потому что этот способ, которым у Вас есть опция маркировки его final, если это имеет смысл для Вашего тестового класса.

2
ответ дан Eddie 5 November 2019 в 09:38
поделиться
Другие вопросы по тегам:

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