Тесты/характеристики iOS TDD/BDD и тестирование на интеграцию и приемку

Каковы лучшие технологии, которые можно использовать для разработки с учетом поведения на iPhone? И каковы некоторые примеры проектов с открытым исходным кодом, которые демонстрируют рациональное использование этих технологий? Вот несколько вариантов, которые я нашел:


Тестирование устройств

Test:: Unit Стиль

RSpec Стиль


Приемочное тестирование

Selenium Стиль

Огурцы Стиль

Дополнения

Заключение

Ну, очевидно, нет правильного ответа на этот вопрос, но вот то, что я сейчас выбираю:

Для модульного тестирования я использовал OCUnit/SenTestingKit в XCode 4. Он прост и прочен. Но я предпочитаю язык BDD над TDD (Почему RSpec лучше, чем Test:: Unit?), Потому что наши слова создают наш мир. Итак, теперь я использую Kiwi with ARC и Завершение/автозаполнение кода Kiwi. Я предпочитаю Kiwi над Cedar, потому что он построен на вершине OCUnit и поставляется с макетами типа RSpec и mocks/stub. UPDATE: теперь я смотрю на OCMock, потому что в настоящее время Kiwi не поддерживает обрезание беспошлинных мостовых объектов.

Для приемочных испытаний я использую автоматизацию пользовательского интерфейса, потому что это потрясающе. Он позволяет записывать каждый тестовый пример, делая автоматические письменные тесты. Кроме того, Apple развивает его, и поэтому у него есть многообещающее будущее. Он также работает на устройстве и с приборами, что позволяет использовать другие интересные функции, например, показывать утечки памяти. К сожалению, с помощью UI Automation я не знаю, как запустить код Objective-C, но с помощью Frank и iCuke вы можете. Итак, я просто тестирую материал Objective-C с модульными тестами или создаю UIButton только для конфигурации TEST, которая при нажатии, будет запускать Objective-C код.

Какие решения вы используете?

Вопросы, относящиеся

Ответ 1

TL;DR

В Pivotal мы написали Cedar, потому что мы используем и любим Rspec в наших проектах Ruby. Кедр не предназначен для замены или конкуренции с OCUnit; это означало возможность тестирования BDD-стиля на Objective C, так же как Rspec впервые испытал BDD-стиль в Ruby, но не исключил Test:: Unit. Выбор того или другого во многом зависит от предпочтений стиля.

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

Длинный ответ

Решение двух структур тестирования, таких как Cedar и OCUnit (например), сводится к двум вещам: предпочтительный стиль и простота использования. Я начну с стиля, потому что это просто вопрос мнения и предпочтения; легкость использования, как правило, представляет собой набор компромиссов.

Приоритеты стиля превосходят ту технологию или язык, которые вы используете. Модульное тестирование в стиле xUnit прошло гораздо дольше, чем тестирование в стиле BDD, но последнее быстро завоевало популярность, в основном благодаря Rspec.

Основным преимуществом тестирования в стиле xUnit является его простота и широкое внедрение (среди разработчиков, которые пишут единичные тесты); почти любой язык, на котором вы могли бы подумать о написании кода, имеет доступную инфраструктуру стиля xUnit.

Структуры в стиле BDD имеют два основных отличия по сравнению с xUnit-style: как вы структурируете тест (или спецификации) и синтаксис для написания ваших утверждений. Для меня структурное различие является основным отличием. Тесты xUnit являются одномерными, с одним методом setUp для всех тестов в данном тестовом классе. Однако классы, которые мы тестируем, не одномерны; нам часто приходится тестировать действия в нескольких разных, потенциально конфликтных контекстах. Например, рассмотрим простой класс ShoppingCart с методом addItem: (для целей этого ответа я использую синтаксис Objective C). Поведение этого метода может различаться, если тележка пуста по сравнению с тем, когда в корзине есть другие предметы; он может отличаться, если пользователь ввел код скидки; он может отличаться, если указанный элемент не может быть отправлен выбранным способом доставки; и т.д. Поскольку эти возможные условия пересекаются друг с другом, вы получаете геометрически увеличивающееся число возможных контекстов; при тестировании в стиле 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, ^{
            ...
        });
    });
});

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

Второе основное отличие между фреймами в стиле BDD и фреймворками стиля xUnit, синтаксисом assertion (или "matcher" ) просто упрощает стиль спецификаций; некоторым людям это очень нравится, другие - нет.

Это приводит к вопросу о простоте использования. В этом случае каждая структура имеет свои плюсы и минусы:

  • OCUnit работает гораздо дольше, чем Cedar, и интегрируется непосредственно в Xcode. Это означает, что просто создать новую целевую аудиторию и, в большинстве случаев, получать тесты и работать "просто работает". С другой стороны, мы обнаружили, что в некоторых случаях, например, запуск на устройстве iOS, получение тестов OCUnit практически невозможно. Настройка спецификаций Cedar требует больше работы, чем тесты OCUnit, поскольку вы сами получили библиотеку и ссылку против нее (никогда не тривиальная задача в Xcode). Мы работаем над упрощением настройки, и любые предложения более чем приветствуются.

  • OCUnit запускает тесты как часть сборки. Это означает, что вам не нужно запускать исполняемый файл, чтобы выполнить ваши тесты; если какие-либо тесты не пройдут, ваша сборка завершится неудачно. Это упрощает процесс прогона тестов на один шаг, а тестовый вывод поступает непосредственно в окно вывода сборки, что упрощает его просмотр. Мы решили использовать спецификации Cedar в исполняемом файле, который вы запускаете отдельно по нескольким причинам:

    • Мы хотели иметь возможность использовать отладчик. Вы запускаете спецификации Cedar так же, как вы запускаете любой другой исполняемый файл, так что вы можете использовать отладчик таким же образом.
    • Нам нужно было просто вести ведение журнала в тестах. Вы можете использовать NSLog() в тестах OCUnit, но вывод идет в окно сборки, где вам нужно развернуть шаг сборки, чтобы прочитать его.
    • Мы хотели легко прочитать тестовую отчетность, как в командной строке, так и в Xcode. Результаты OCUnit хорошо видны в окне построения в Xcode, но построение из командной строки (или как часть процесса CI) приводит к выходу теста, смешанному с множеством других результатов сборки. С отдельными этапами сборки и запуска Cedar отделяет выход так, что тестовый выход легко найти. По умолчанию тестовый бегун Cedar копирует стандартный стиль печати ".". для каждой пропущенной спецификации, "F" для неудачных спецификаций и т.д. Cedar также имеет возможность использовать пользовательские объекты-репортеры, поэтому вы можете получить результаты вывода любым способом, как вам нравится, с небольшими усилиями.
  • OCUnit является официальной платформой тестирования модулей для Objective C и поддерживается Apple. Apple имеет в основном неограниченные ресурсы, поэтому, если они хотят что-то сделать, это будет сделано. И, в конце концов, это песочница Apple, в которой мы играем. Оборотная сторона этой монеты, однако, заключается в том, что Apple получает по заказу запросов на поддержку bajillion и отчетов об ошибках каждый день. Они отлично справляются с обработкой их всех, но они могут не справиться с проблемами, о которых вы сообщаете немедленно или вообще. Кедр намного более новый и менее испеченный, чем OCUnit, но если у вас есть вопросы или проблемы или предложения, отправьте сообщение в список рассылки Cedar ([email protected]), и мы сделаем все возможное, чтобы помочь вам. Кроме того, не стесняйтесь разворачивать код из Github (github.com/pivotal/cedar) и добавлять все, что, по вашему мнению, отсутствует. Мы создаем основы тестирования с открытым исходным кодом по какой-либо причине.

  • Запуск тестов OCUnit на устройствах iOS может быть затруднен. Честно говоря, я не пробовал это в течение довольно долгого времени, поэтому, возможно, это стало проще, но в последний раз, когда я пытался, я просто не мог получить тесты OCUnit для любых функций UIKit. Когда мы писали Cedar, мы убедились, что можем тестировать код, зависящий от UIKit, как на симуляторе, так и на устройствах.

Наконец, мы написали Cedar для модульного тестирования, что означает, что он не очень сопоставим с такими проектами, как UISpec. Прошло довольно много времени с тех пор, как я попытался использовать UISpec, но я понял, что это основное внимание уделяется программному управлению пользовательским интерфейсом на устройстве iOS. Мы специально решили не пытаться, чтобы Cedar поддерживала эти типы спецификаций, так как Apple (в то время) собиралась объявить UIAutomation.

Ответ 2

Мне нужно будет подбросить Frank в микс приемочного тестирования. Это довольно новое дополнение, но до сих пор отлично работало для меня. Кроме того, на самом деле он активно работает, в отличие от icuke и других.

Ответ 3

Для разработки, основанной на тестах, мне нравится использовать GHUnit, ее бриз для настройки и отлично подходит для отладки.

Ответ 4

Отличный список!

Я нашел еще одно интересное решение для приложений IOS для тестирования iOS.

Zucchini Framework

Он основан на UIAutomation. Структура позволяет писать сценарии с использованием сценариев в стиле Огурца. Сценарии могут быть выполнены в Simulator и на устройстве с консоли (это CI-софт).

Утверждения основаны на скриншотах. Звучит негибко, но он дает вам хороший отчет в формате HTML, с выделенным сравнением экрана, и вы можете предоставить маски, которые определяют регионы, в которых вы хотите получить точное подтверждение пикселя.

Каждый экран должен быть описан в CoffeScript, а сам инструмент написан в рубине. Это своего рода полиглоттовый кошмар, но инструмент обеспечивает отличную абстракцию для UIAutomation, и когда экраны описаны, он управляется даже для человека QA.

Ответ 5

Я бы выбрал iCuke для приемочных испытаний и Cedar для модульных тестов. UIAutomation - это шаг в правильном направлении для Apple, но инструменты нуждаются в лучшей поддержке непрерывной интеграции; автоматический запуск тестов UIAutomation с помощью инструментов в настоящее время невозможен, например.

Ответ 6

GHUnit хорош для модульных тестов; для интеграционных тестов я использовал UISpec с некоторым успехом (github fork здесь: https://github.com/drync/UISpec), но я с нетерпением жду попытки iCuke, поскольку это promises, чтобы быть легкой установкой, и вы можете использовать проверку рельсов, например RSpec и Cucumber.

Ответ 7

В настоящее время я использую specta для rspec, как настройки, и его партнер (как упоминалось выше) expecta, у которого есть тонна превосходных вариантов соответствия.

Ответ 8

Мне действительно нравится OCDSpec2, но я предвзятый, я написал OCDSpec и вношу свой вклад во вторую.

Это очень быстро даже на iOS, отчасти потому, что он построен с нуля, а не поверх OCUnit. Он также имеет синтаксис RSpec/Jasmine.

https://github.com/ericmeyer/ocdspec2