тл; д-р
У Pivotal ми написали Cedar, тому що ми використовуємо та любимо Rspec у своїх проектах Ruby. Кедр не призначений замінювати або конкурувати з OCUnit; це покликане принести можливість тестування у стилі BDD до Цілі C, подібно до того, як Rspec піонірував тестування стилю BDD у Ruby, але не усунув Test :: Unit. Вибір того чи іншого багато в чому залежить від стильових уподобань.
В деяких випадках ми розробили Cedar, щоб подолати деякі недоліки в роботі OCUnit для нас. Зокрема, ми хотіли мати можливість використовувати налагоджувач у тестах, запускати тести з командного рядка та в CI-складах та отримувати корисне виведення тексту результатів тестів. Ці речі можуть бути вам більш-менш корисними.
Довга відповідь
Вибираючи між двома тестовими рамками, такими як Cedar та OCUnit (наприклад), зводиться до двох речей: бажаний стиль та простота використання. Почну зі стилю, бо це просто питання думки та уподобань; простота використання, як правило, є сукупністю компромісів.
Міркування щодо стилю виходять за технологію чи мову, якими ви користуєтесь. Тестування одиниць у стилі xUnit вже довше, ніж тестування у стилі BDD, але остання швидко набула популярності, багато в чому завдяки Rspec.
Основною перевагою тестування в стилі xUnit є його простота та широке використання (серед розробників, які пишуть одиничні тести); Практично на будь-якій мові, з якої ви можете розглянути можливість написання коду, є рамка стилю xUnit.
Рамки в стилі BDD мають, як правило, дві основні відмінності порівняно з xUnit-стилем: те, як ви структуруєте тест (або характеристики), і синтаксис для написання ваших тверджень. Для мене структурна різниця є головним диференціатором. Тести xUnit є одновимірними, з одним методом setUp для всіх тестів у заданому тестовому класі. Класи, які ми протестуємо, проте не є одновимірними; нам часто потрібно перевірити дії в декількох різних, потенційно конфліктних, контекстах. Наприклад, розглянемо простий клас ShoppingCart з методом addItem: (для цілей цієї відповіді я буду використовувати синтаксис Objective C). Поведінка цього методу може відрізнятися, коли візок порожній порівняно з тим, коли в кошику містяться інші елементи; він може відрізнятися, якщо користувач ввів код знижки; він може відрізнятися, якщо вказаний елемент може " t буде відвантажена обраним способом доставки; і т.д. Оскільки ці можливі умови перетинаються між собою, ви отримуєте геометрично зростаючу кількість можливих контекстів; У тестуванні стилю xUnit це часто призводить до безлічі методів з такими іменами, як testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Структура кадрів у стилі BDD дозволяє організувати ці умови індивідуально, що, як я вважаю, полегшує переконання, що я охоплюю всі випадки, а також простіше знайти, змінити або додати індивідуальні умови. Як приклад, використовуючи синтаксис Cedar, наведений вище метод виглядатиме так: У тестуванні стилю xUnit це часто призводить до безлічі методів з такими іменами, як testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Структура кадрів у стилі BDD дозволяє організувати ці умови індивідуально, що, як я вважаю, полегшує переконання, що я охоплюю всі випадки, а також простіше знайти, змінити або додати індивідуальні умови. Як приклад, використовуючи синтаксис Cedar, наведений вище метод виглядатиме так: У тестуванні стилю xUnit це часто призводить до безлічі методів з такими іменами, як testAddItemWhenCartIsEmptyAndNoDiscountCodeAndShippingMethodApplies. Структура кадрів у стилі BDD дозволяє організувати ці умови індивідуально, що, як я вважаю, полегшує переконання, що я охоплюю всі випадки, а також простіше знайти, змінити або додати індивідуальні умови. Як приклад, використовуючи синтаксис Cedar, наведений вище метод виглядатиме так:
describe(@"ShoppingCart", ^{
describe(@"addItem:", ^{
describe(@"when the cart is empty", ^{
describe(@"with no discount code", ^{
describe(@"when the shipping method applies to the item", ^{
it(@"should add the item to the cart", ^{
...
});
it(@"should add the full price of the item to the overall price", ^{
...
});
});
describe(@"when the shipping method does not apply to the item", ^{
...
});
});
describe(@"with a discount code", ^{
...
});
});
describe(@"when the cart contains other items, ^{
...
});
});
});
У деяких випадках ви знайдете контексти, що містять ті самі набори тверджень, які ви можете ЗУБИТИ, використовуючи загальні приклади.
Друга основна відмінність фреймворків у стилі BDD від фреймворків у стилі xUnit, твердження (або "матчер") синтаксису, просто робить стиль специфікацій дещо приємнішим; деяким людям це дуже подобається, іншим - ні.
Це призводить до питання про простоту використання. У цьому випадку кожен фреймворк має свої плюси і мінуси:
OCUnit існує набагато довше, ніж Cedar, і він інтегрується безпосередньо в Xcode. Це означає, що зробити нову цільову ціль просто, і, як правило, тестування та запуск "просто працює". З іншого боку, ми виявили, що в деяких випадках, наприклад, запускаючи на пристрої iOS, отримати тести OCUnit на роботу було майже неможливо. Налаштування специфікацій Cedar вимагає дещо більше роботи, ніж тести OCUnit, оскільки ви отримаєте бібліотеку і посилаєтесь на неї самостійно (ніколи не тривіальне завдання в Xcode). Ми працюємо над полегшенням налаштування, і будь-які пропозиції більш ніж вітаються.
OCUnit виконує тести як частину збірки. Це означає, що для запуску тестів вам не потрібно запускати виконуваний файл; якщо якісь тести не вдається, ваша збірка не вдасться. Це робить процес запуску тестів на один крок простішим, а тестовий вихід безпосередньо надходить у вікно виводу збірки, що дозволяє легко бачити. Ми вирішили створити специфікації Cedar у виконуваний файл, який ви запускаєте окремо з кількох причин:
- Ми хотіли використовувати відладчик. Ви запускаєте характеристики Cedar так само, як і будь-який інший виконуваний файл, тому ви можете використовувати відладчик таким же чином.
- Ми хотіли легкої консольної реєстрації в тестах. Ви можете використовувати NSLog () в тестах OCUnit, але результат надходить у вікно збірки, де вам потрібно розгорнути крок збирання, щоб прочитати його.
- Ми хотіли легко читати тестові звіти, як у командному рядку, так і в Xcode. Результати OCUnit добре відображаються у вікні збірки в Xcode, але побудова з командного рядка (або як частина процесу CI) призводить до тестового виводу, змішаного з безліччю та безліччю інших результатів збірки. З окремими фазами збірки та запуску Кедр відокремлює вихід, тому тестовий вихід легко знайти. Тестовий бігун Cedar за замовчуванням копіює стандартний стиль друку ". для кожної специфікації, що проходить, "F" для несправних специфікацій тощо. "Кедр" також має можливість використовувати спеціальні репортерські об'єкти, тому ви можете мати результати виведення будь-якого способу, який вам подобається, доклавши невеликих зусиль.
OCUnit є офіційною основою тестування модулів для Objective C і підтримується Apple. У Apple, в основному, необмежені ресурси, тому, якщо вони хочуть щось зробити, це зробиться. Зрештою, це пісочниця Apple, в яку ми граємо. Однак, перевернення цієї монети полягає в тому, що Apple щодня отримує замовлення на мільярд запитів про підтримку та повідомлення про помилки. Вони надзвичайно добре впораються з усіма ними, але вони можуть не впоратися з проблемами, про які ви повідомляєте негайно, або взагалі. Кедр набагато новіший і менш запечений, ніж OCUnit, але якщо у вас є питання або проблеми чи пропозиції, надішліть повідомлення в список розсилки Cedar (cedar-discuss@googlegroups.com), і ми зробимо все, що можна, щоб допомогти вам. Крім того, сміливо роздрібніть код від Github (github.com/pivotal/cedar) і додайте все, що, на вашу думку, відсутнє.
Запуск тестів OCUnit на пристроях iOS може бути складним. Чесно кажучи, я не пробував це досить довгий час, тому, можливо, це стало простіше, але останній раз, коли я спробував, я просто не зміг отримати тести OCUnit для роботи будь-якої функції UIKit. Коли ми писали Cedar, ми переконалися, що можемо перевірити залежний від UIKit код як на тренажері, так і на пристроях.
Нарешті, ми написали Cedar для тестування одиниць, це означає, що він насправді не порівнянний з такими проектами, як UISpec. Минуло багато часу, як я спробував використовувати UISpec, але я зрозумів, що він зосереджений насамперед на програмному керуванні інтерфейсу на пристрої iOS. Ми спеціально вирішили не намагатися Cedar підтримувати такі типи специфікацій, оскільки Apple (у той час) збиралася оголосити UIAutomation.