2014-01-10 4 views
38

За комментарий в шаблоне по умолчанию для XCTestCase относительно setUp:Какова цель метода setUp XCTestCase?

Put setup code here; it will be run once, before the first test case.

Однако в XCTestCase.h, комментарий выше setUp государств по-разному:

Setup method called before the invocation of each test method in the class.

Чтобы подтвердить фактическое поведение, Я положил NSLog в пределах setUp, чтобы подсчитать, сколько раз он был вызван:

static int count = 0; 

- (void)setUp 
{ 
    [super setUp]; 
    count++; 

    NSLog(@"Call Count = %d", count); 
} 

Это привело к методу setUp вызывается перед каждым методом испытаний (подтверждающим комментарий на XCTestCase.h).

Я хотел использовать метод setUp для создания объектов тестирования/макета один раз (например, для установки тестового стека Core Data). Их создание снова и снова было бы интенсивным и потенциально очень медленным.

Так,

1) Что setUp на самом деле предназначены для использования? Наверняка разработчики не создают в нем объекты снова и снова?

2) Как создать эти объекты только один раз в пределах XCTestCase?

ответ

86

Есть несколько моментов для обсуждения здесь: поведение методов setUp и общие лучшие методы тестирования.

Есть на самом деле дваsetUp методы:

+ (void)setUp; 
- (void)setUp; 

Метод класса (+ (void)setUp) выполняется только один раз в течение всего испытания.

Метод экземпляра (- (void)setUp) - это шаблон в шаблоне по умолчанию; он запускается перед каждым тестом. Будем надеяться, что в гипотетической будущей версии Xcode этот комментарий будет изменен на // Put setup code here. This method is called before the invocation of each test method in the class. WINK WINK

Итак, используя эти два метода, оба описанных вами поведения возможны.

Что касается вашего комментария: «? Конечно, разработчики не создавать объекты в нем снова и снова»

Ответом будет «Да, они обычно есть».Популярный акроним для 'хороших' единичных испытаний ПЕРВЫЙ:

  • Fast
  • Изолированные
  • Повторяется
  • Self-Верификация
  • Своевременное

Изолированные является ключом к этому обсуждение: ваши тесты не должны полагаться на предыдущее состояние, оставшееся после других тестов. В идеале вы должны снести и восстановить свой стек Core Data в памяти для каждого теста, чтобы вы знали, что начинаете с чистого листа. Хорошим примером является this post by Graham Lee. Вы хотите использовать стек в памяти, потому что: a) вы можете легко выбросить его, и b) он должен быть очень быстрым, потому что он просто встроен в память и не ударяет по вашему диску.

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

+2

+1: Замечательный ответ! Да, думая об этом, * 1) заказ на проверку не гарантируется * (но при хороших тестах, не имеет значения, что происходит, когда) и * 2) тесты не должны влиять на то, что делают другие тесты * (as вы говорите, что они «не должны полагаться на какое-либо предыдущее тестовое состояние»). Хорошая идея со стеком 'in-memory'. Это именно то, что я буду делать. –

+0

Прочитав этот ответ, я сразу же удалил мой +1;) Просто примечание: XCTest - это более или менее копия SenTest, наследующая все свои ограничения. Существуют гораздо лучшие рамки тестирования, которые имеют группы, которые могут быть произвольно вложены, где процедура _setup_ и _teardown_ очевидна. К сожалению, Xcode и XCTest далеко позади, и интеграция действительно классных сторонних модулей тестирования в захватывающий тестовый фрейм Xcode довольно сложна. – CouchDeveloper

+0

@ JRG-Developer Правильно - тестовый заказ не гарантируется. @CouchDeveloper Например, [specta] (https://github.com/specta/specta) имеет методы 'beforeEach',' beforeAll', 'afterEach' и' afterAll'. –

3

Я пришел сюда с почти той же проблемой: как выполнить setUpтолько один раз и в Swift. Вот решение:

override class func setUp() { 
    super.setUp()  
    // ... 
} 

override class func tearDown() {  
    // ... 
    super.tearDown() 
} 

Сейчас я до сих пор ищу решение для асинхронныхsetUp!

+4

Асинхронный setUp не будет полезен, поскольку по определению вы хотите, чтобы ваш setUp был завершен, прежде чем запускать какой-либо тест в этом классе. –

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