Настраивать отдельные случаи XCTest unit test в Xcode 5 на конкретное устройство iOS для универсального приложения?

Я создаю универсальное приложение для iPhone/iPad, и в некоторых случаях пользовательский интерфейс существенно отличается (например, на iPhone мы используем парадигму Master/Detail с TableViews, тогда как на iPad мы используем CollectionView с ячейками, которые содержат детали).

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

Итак, мой вопрос заключается в том, что в универсальном приложении, создаваемом с использованием Xcode 5 с фреймворком XCTest, можно ли настраивать отдельные случаи/классы unit test, которые будут выполняться на определенных физических устройствах?

Я столкнулся с аналогичным вопросом здесь - iOS Unit testing универсальное приложение - но у искателя были разные намерения и использовались более старые технологии.

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

Заранее благодарим за ваши предложения.

- EDIT -

@TommieC привел меня к тому, что кажется подходящим путем, если руководство для smidge. Я создал две новые схемы тестирования, один для устройств с размером телефона и один для устройств размером с планшет. Внутри этих схем я редактировал тестовую часть и добавлял в основные тесты вместе с тестами, специфичными для устройства.

Затем у меня есть jenkins, выполняющие два шага сборки, предназначенные для соответствующих устройств для проверки конкретной схемы. Недостатком этого подхода является два этапа сборки. Тем не менее, я планирую разделить работу jenkins и запустить ее на 2 подчиненных устройствах, при этом соответствующие устройства подключаются к каждому, чтобы распараллелить тестирование.

AFAIK это также будет дружественным Xcode Build Services, так как он работает на основе схем в проекте. Это очень плохо, для этого нет ничего более элегантного, встроенного в XCTest, учитывая, что это не очень хорошо масштабируется в случае появления нового типа устройства (часы/телевизор/фен/и т.д.).

Ответы

Ответ 1

Чтобы настроить целевые тесты на устройства, необходимо отредактировать схемы для проекта. В разделе "Продукты" > "Схема" > "Редактировать схемы" можно выбрать выбор конкретных тестов для каждого устройства.

Scheme Editor

Ответ 2

Вот мое предлагаемое решение.

Разделите свои тесты на конкретные iPhone и специальные тесты iPad.

Теперь добавьте новый Target (Cocoa Touch Unit Testing Bundle) специально для iPhone или iPad. Если у вас уже есть много распространенных тестов, может быть более разумным дублировать текущую целевую аудиторию.

Теперь убедитесь, что ваши конкретные тестовые классы для iPhone включены только в ваш тестовый тест iPhone, нажав на класс в Навигаторе, а затем откройте панель "Утилиты". Вы можете установить, к какой цели относится ваш класс, используя флажки Target Membership.

Target Membership panel

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

Ответ 3

Я хотел сделать то же самое и наткнулся на этот старый пост. Мое решение включает в себя присвоение имен определенным тестам устройств, которые заканчиваются на "Pad" или "Phone", а затем фильтрацию списка тестов для включения текущих тестов устройств:

class MyTests: XCTestCase {
    override class var defaultTestSuite: XCTestSuite {
        let suite = XCTestSuite(forTestCaseClass: MyTests.self)

        let newSuite = XCTestSuite(name: "MyTests")
        for test in suite.tests {
            // Name is of the form "-[MyTests test*]"
            if test.name.hasSuffix("Pad]") {
                // iPad only test
                if UIDevice.current.userInterfaceIdiom == .pad {
                    newSuite.addTest(test)
                }
            }
            else if test.name.hasSuffix("Phone]") {
                // iPhone only test
                if UIDevice.current.userInterfaceIdiom == .phone {
                    newSuite.addTest(test)
                }
            }
            else {
                // Can run on both devices
                newSuite.addTest(test)
            }
        }

        return newSuite
    }

    func testAll() { // All devices test }
    func testOnlyPad() { // iPad only test }
    func testOnlyPhone() { // iPhone only test }
}