matches
пытается сопоставить выражение со всей строкой и неявно добавить ^
в начале и $
в конце вашего шаблона, то есть не будет искать подстроку. Следовательно, выход этого кода:
public static void main(String[] args) throws ParseException {
Pattern p = Pattern.compile("\\d\\d\\d");
Matcher m = p.matcher("a123b");
System.out.println(m.find());
System.out.println(m.matches());
p = Pattern.compile("^\\d\\d\\d$");
m = p.matcher("123");
System.out.println(m.find());
System.out.println(m.matches());
}
/* output:
true
false
true
true
*/
123
является подстрокой a123b
, поэтому метод find()
выводит true. matches()
только «видит» a123b
, который не совпадает с 123
и, следовательно, выводит false.
Вы можете отключить его, установив для параметра sortTestMethodsUsing значение None: http://docs.python.org/2/library/unittest.html#unittest.TestLoader.sortTestMethodsUsing
Для чистых единомышленников вы правы; но для тестирования компонентов и интеграционных тестов ... Я не согласен с тем, что вы ничего не будете предполагать о состоянии. Что делать, если вы проверяете состояние. Например, ваш тест подтверждает, что услуга автоматически запускается после установки. Если в вашей настройке вы запустите службу, затем выполните утверждение, то вы больше не проверяете состояние, но вы проверяете функциональность «запуск службы».
Еще один пример: когда ваша установка занимает длительное время времени или требует много места, и просто становится непрактичным частое выполнение установки.
Многие разработчики, как правило, используют «unittest» рамки для тестирования компонентов ... так что остановитесь и спросите себя, я делаю unittesting или компонентного тестирования.
Философия модульных тестов заключается в том, чтобы сделать их независимыми друг от друга. Это означает, что первым шагом каждого теста всегда будет попытка переосмыслить, как вы тестируете каждую часть, чтобы соответствовать этой философии. Это может повлиять на то, как вы подходите к тестированию и творчеству, сужая ваши тесты до меньших областей.
Однако, если вы все еще обнаружите, что вам нужны тесты в определенном порядке (поскольку это жизнеспособно), вы можете попробовать проверяя ответ на Python unittest.TestCase порядок выполнения .
http://docs.python.org/library/unittest.html
Обратите внимание, что порядок, в котором будут выполняться различные тестовые примеры, определяется путем сортировки имен тестовых функций по отношению к встроенному упорядочению для строк.
blockquote>Если вам нужно установить порядок явно, используйте монолитный тест.
class Monolithic(TestCase): def step1(self): ... def step2(self): ... def steps(self): for name in sorted(dir(self)): if name.startswith("step"): yield name, getattr(self, name) def test_steps(self): for name, step in self.steps(): try: step() except Exception as e: self.fail("{} failed ({}: {})".format(step, type(e), e)
Подробнее см. post .
Если вы используете «нос», и вы пишете свои тестовые примеры как функции (а не как методы какого-либо производного класса TestCase), «нос» не возится с порядком, а использует порядок функций, определенный в файл. Чтобы методы assert_ * были удобными без необходимости подкласса TestCase, я обычно использую модуль тестирования из numpy. Пример:
from numpy.testing import *
def test_aaa():
assert_equal(1, 1)
def test_zzz():
assert_equal(1, 1)
def test_bbb():
assert_equal(1, 1)
Выполнение этого с помощью '' nosetest -vv '' дает:
test_it.test_aaa ... ok
test_it.test_zzz ... ok
test_it.test_bbb ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.050s
OK
Обратите внимание на всех тех, кто утверждает, что модульные тесты не должны быть заказаны: while это правда, что модульные тесты должны быть изолированы и могут выполняться независимо, ваши функции и классы обычно не являются независимыми. Они скорее наращивают друг друга от более простых / низкоуровневых функций до более сложных / высокоуровневых функций. Когда вы начинаете оптимизировать свои низкоуровневые функции и испортить (со своей стороны, я делаю это часто, а если нет, вам, вероятно, не нужен единичный тест;), то это намного лучше для диагностики причины, когда сначала выполняются тесты для простых функций и тесты для функций, которые позже зависят от этих функций. Если тесты сортируются в алфавитном порядке, реальная причина обычно затухает среди сто неудачных утверждений, которых нет, потому что у тестируемой функции есть ошибка, а потому, что функция низкого уровня, на которую она опирается, имеет.
Вот почему я хочу, чтобы мои модульные тесты сортировались так, как я их указывал: не использовать состояние, которое было создано в ранних тестах в последующих тестах, но как очень полезный инструмент для диагностики проблем.
Существует ряд причин для определения приоритетов тестов, не последним из которых является производительность, для чего предназначен JUnit Max. Иногда бывает полезно проводить очень медленные тесты в своем собственном модуле, чтобы вы могли быстро получить отзывы от тех тестов, которые не страдают от тех же тяжелых зависимостей. Заказ также полезен для отслеживания сбоев в тестах, которые не являются полностью автономными.
a
, а b
и b
- a
. Тогда гораздо лучше, если test_a
выполняется до test_b
, потому что если a
содержит ошибку, вы увидите это намного раньше, вместо того, чтобы пытаться найти ошибку в b
.
– Elmar Zander
13 March 2012 в 18:30
test_b
работает также a
, тогда у вас может возникнуть проблема с вашей тестовой структурой, так как test_b
завершит тестирование не одной единицы b
, а двух: b
и a
. Вероятно, вы должны издеваться над результатом a
в своем test_b
. Единичные тесты ≠ интеграционные тесты.
– mac
23 December 2013 в 15:29
Хорошо, может быть немного позже, но в любом случае ...
Вы должны попробовать библиотеку proboscis . Это позволит вам сделать заказ на тестирование, а также настроить любые тестовые зависимости. Я использую его, и эта библиотека действительно потрясающая.
Например, если test case #1
из module A
должно зависеть от test case #3
от module B
, вы можете установить это поведение с помощью библиотеки.
В отличие от сказанного здесь: - тесты должны выполняться изолированно (порядок не должен иметь значения для этого) И - упорядочение их важно, потому что они описывают, что система делает и как разработчик реализует ее.
IOW, каждый тест дает вам информацию о системе и логике разработки.
Итак, если эти данные не упорядочены, что может затруднить понимание вашего кода.
Я согласен с тем, что тесты не могут быть заказаны. В некоторых случаях это помогает (проще, черт возьми!) Иметь их в порядке ... в конце концов, это причина для «единицы» в UnitTest.
Тем не менее, одна из альтернатив - использовать макетные объекты для mockout и исправлять элементы, которые должны выполняться до того, как тестируется этот конкретный код. Вы также можете поместить туда фиктивную функцию, чтобы обезопасить свой код. Для получения дополнительной информации ознакомьтесь с Mock, который теперь является частью стандартной библиотеки. Mock
Вот несколько видеороликов YouTube, если вы еще не использовали Mock раньше.
Подробнее, попробуйте использовать методы класса для структурирования вашего кода, затем поместите все методы класса в одном основном методе тестирования.
import unittest
import sqlite3
class MyOrderedTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.create_db()
cls.setup_draft()
cls.draft_one()
cls.draft_two()
cls.draft_three()
@classmethod
def create_db(cls):
cls.conn = sqlite3.connect(":memory:")
@classmethod
def setup_draft(cls):
cls.conn.execute("CREATE TABLE players ('draftid' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 'first', 'last')")
@classmethod
def draft_one(cls):
player = ("Hakeem", "Olajuwon")
cls.conn.execute("INSERT INTO players (first, last) VALUES (?, ?)", player)
@classmethod
def draft_two(cls):
player = ("Sam", "Bowie")
cls.conn.execute("INSERT INTO players (first, last) VALUES (?, ?)", player)
@classmethod
def draft_three(cls):
player = ("Michael", "Jordan")
cls.conn.execute("INSERT INTO players (first, last) VALUES (?, ?)", player)
def test_unordered_one(self):
cur = self.conn.execute("SELECT * from players")
draft = [(1, u'Hakeem', u'Olajuwon'), (2, u'Sam', u'Bowie'), (3, u'Michael', u'Jordan')]
query = cur.fetchall()
print query
self.assertListEqual(query, draft)
def test_unordered_two(self):
cur = self.conn.execute("SELECT first, last FROM players WHERE draftid=3")
result = cur.fetchone()
third = " ".join(result)
print third
self.assertEqual(third, "Michael Jordan")
См. пример WidgetTestCase
в http://docs.python.org/library/unittest.html#organizing-test-code , он говорит, что
Теперь экземпляры класса будут запускать один из методов test * * (), при этом self.widget будет создан и уничтожен отдельно для каждого экземпляра.
blockquote>Поэтому было бы бесполезно указывать порядок тестовых случаев, если вы не имеете доступа к глобальным переменным.
Простым методом для упорядочения тестов «unittest» является следовать механизму init.d, давая им числовые имена:
def test_00_createEmptyObject(self):
obj = MyObject()
self.assertIsEqual(obj.property1, 0)
self.assertIsEqual(obj.dict1, {})
def test_01_createObject(self):
obj = MyObject(property1="hello", dict1={"pizza":"pepperoni"})
self.assertIsEqual(obj.property1, "hello")
self.assertIsDictEqual(obj.dict1, {"pizza":"pepperoni"})
def test_10_reverseProperty(self):
obj = MyObject(property1="world")
obj.reverseProperty1()
self.assertIsEqual(obj.property1, "dlrow")
Однако в таких случаях вам может потребоваться структурировать ваши тесты иначе, чтобы вы могли опираться на предыдущие случаи строительства. Например, в вышесказанном, может иметь смысл иметь функцию «construct и veirfy», которая строит объект и проверяет его назначение параметров.
def make_myobject(self, property1, dict1): # Must be specified by caller
obj = MyObject(property1=property1, dict1=dict1)
if property1:
self.assertEqual(obj.property1, property1)
else:
self.assertEqual(obj.property1, 0)
if dict1:
self.assertDictEqual(obj.dict1, dict1)
else:
self.assertEqual(obj.dict1, {})
return obj
def test_00_createEmptyObject(self):
obj = self.make_object(None, None)
def test_01_createObject(self):
obj = self.make_object("hello", {"pizza":"pepperoni"})
def test_10_reverseProperty(self):
obj = self.make_object("world", None)
obj.reverseProperty()
self.assertEqual(obj.property1, "dlrow")
Существуют сценарии, в которых порядок может быть важен и где setUp и Teardown входят в число ограниченных. Существует только один метод setUp и tearDown, который является логичным, но вы можете добавлять только столько информации в них, пока не получите непонятное, что может делать setUp или tearDown.
Возьмем этот тест интеграции в качестве примера:
Вы пишете тесты, чтобы проверить, работают ли форма регистрации и форма входа. В таком случае порядок важен, так как вы не можете войти в систему без существующей учетной записи. Что еще более важно, порядок ваших тестов представляет собой какое-то взаимодействие с пользователем. Где каждый тест может представлять собой шаг во всем процессе или потоке, который вы тестируете.
blockquote>Разделение кода на эти логические фрагменты имеет несколько преимуществ.
Не может быть лучшим решением, но я часто использую один метод, который запускает фактические тесты.
def test_registration_login_flow(self): _test_registration_flow() _test_login_flow()
Я согласен с утверждением, что ответ «не делай этого» - плохая реакция.
У меня похожая ситуация, когда у меня есть один источник данных, и один тест уничтожит набор данных, в результате чего другие тесты будут терпеть неудачу.
Мое решение состояло в том, чтобы использовать переменные среды операционной системы на моем сервере Bamboo ...
(1) Тест для функции «очистки данных» начинается с цикла while, который проверяет состояние переменной среды «BLOCK_DATA_PURGE». Если переменная «BLOCK_DATA_PURGE» больше нуля, цикл будет записывать запись журнала о том, что он спал 1 секунду. После того, как «BLOCK_DATA_PURGE» имеет нулевое значение, выполнение переходит к проверке функциональности очистки.
(2) Любой юнит-тест, который нуждается в данных в таблице, просто увеличивает «BLOCK_DATA_PURGE» в начале (в настройке ( )) и уменьшает одну и ту же переменную в режиме teardown ().
Эффект этого заключается в том, чтобы позволить различным потребителям данных блокировать функциональность чистки до тех пор, пока они нуждаются, не опасаясь, что чистка может выполняться между тестами. Эффективно операция чистки продвигается до последнего шага ... или, по крайней мере, последнего шага, требующего первоначального набора данных.
Сегодня я собираюсь расширить это, чтобы добавить дополнительные функции, чтобы позволить некоторым тестам REQUIRE_DATA_PURGE , Они будут эффективно инвертировать вышеуказанный процесс, чтобы гарантировать, что эти тесты выполняются только после очистки данных для проверки восстановления данных.
Нет причин, по которым вы не можете опираться на то, что было сделано в предыдущем тесте, или должны перестроить все это с нуля для следующего теста. По крайней мере, нет причин, по которым обычно предлагают, но люди просто уверенно говорят «не стоит». Это не полезно.
В общем, я устал читать слишком много ответов здесь, которые говорят в основном «вы не должны этого делать» вместо того, чтобы давать какую-либо информацию о том, как лучше всего это делать, если в вопрошающих Суждение есть веские основания для этого. Если бы я хотел, чтобы чье-то мнение о том, нужно ли мне что-то делать, я бы попросил мнения о том, делать ли это хорошую идею.
. Из-за этого, если вы читаете say loadTestsFromTestCase и то, что он вызывает, он в конечном счете сканирует методы с некоторым шаблоном имени в любом порядке, в котором они встречаются в словаре методов классов, поэтому в основном в порядке ключа. Он принимает эту информацию и делает testuite для сопоставления ее с классом TestCase. Предоставляя ему вместо этого список, который вы хотите заказать, это один из способов сделать это. Я не уверен в самом эффективном / чистом способе сделать это, но это действительно работает.
Не полагайтесь на заказ. Если они используют какое-то общее состояние, например файловую систему или базу данных, тогда вы должны создать методы setUp
и tearDown
, которые превратят вашу среду в проверяемое состояние, а затем очистят после запуска тестов. Каждый тест должен предполагать, что среда определена в setUp
и не должна делать никаких дополнительных предположений.
Зачем вам нужен специальный тестовый заказ? Тесты должны быть изолированы, и поэтому их можно запускать в любом порядке или даже параллельно.
Если вам нужно проверить что-то вроде отмены подписки на пользователя, тест может создать новую базу данных с тестом подписки, а затем попробуйте отказаться от подписки. У этого сценария есть свои проблемы, но в итоге он лучше, чем тесты зависят друг от друга. (Обратите внимание, что вы можете разложить общий тестовый код, так что вам не нужно повторять код установки БД или создавать тестовые данные для рекламы.)