将Xcode 5中的单个XCTest单元测试用例定位到适用于通用应用程序的特定iOS设备?

时间:2013-10-25 15:55:01

标签: ios iphone xcode unit-testing xcode5

我正在构建一个通用的iPhone / iPad应用程序,在某些情况下UI会有很大的不同(例如在iPhone上我们使用带有TableView的Master / Detail范例,而在iPad上我们使用带有包含Cell的单元格的CollectionView细节)。

因为接口是如此不同,它会改变构建视图控制器的单元测试的方式。在集合视图中,我们必须进行测试以确保单元格正确构建并包含所有详细信息,而在iPhone上我们需要两组测试 - 一个用于主列表,一个用于详细信息屏幕。

所以我的问题是,在使用Xcode 5和XCTest框架构建的通用应用程序中,您是否可以将单个单元测试用例/类目标设置为在特定的物理设备上运行?

我在这里遇到了一个类似的问题 - iOS Unit testing universal application - 但提问者有不同的意图,并且正在使用旧技术。

我也看到了对 UserInterfaceIdiom 的各个测试函数进行检查的建议,但这看起来很粗糙。理想情况下,会有一个注释指定在特定设备上运行的特定测试,或者能够为特定设备指定整个测试类。

提前感谢您的建议。

- 编辑 -

@TommieC让我失去了似乎是合适的道路,如果是一个微薄的手册。我创建了两个新的测试特定方案,一个用于手机大小的设备,另一个用于平板电脑大小的设备。在这些方案中,我编辑了测试部分,并在核心测试中添加了特定于设备的测试。

然后我让jenkins执行两个构建步骤,针对相应的设备来测试特定的方案。这种方法的缺点是两个构建步骤。但是,我计划拆分jenkins作业并在2个从站上运行它,并将相应的设备连接到每个从站以并行化测试。

AFAIK这也将是Xcode构建服务友好的,因为它也基于项目中的方案工作。这真的太糟糕了,XCTest没有更优雅的内置,考虑到在新的设备类型发挥作用(手表/电视/吹风机等)时不能很好地扩展。

3 个答案:

答案 0 :(得分:2)

要定位特定于设备的测试,需要编辑项目的方案。在产品>下方案>编辑方案可以选择为每个设备选择特定于设备的测试。

Scheme Editor

答案 1 :(得分:1)

这是我提议的解决方案。

将您的测试分解为iPhone特定测试和iPad特定测试。

现在为iPhone或iPad添加一个新的Target(Cocoa Touch Unit Testing Bundle)。如果您已经编写了许多常见测试,那么复制当前测试目标可能更为谨慎。

现在,通过单击导航器中的类,确保您的iPhone特定测试类仅包含在iPhone测试目标中,然后打开“工具”面板。您可以使用“目标成员资格”复选框设置您的类所属的目标。

Target Membership panel

要扩展此功能,您可以为两个目标添加不同的方案,以便更快地运行测试。

答案 2 :(得分:0)

我一直想做同样的事情,并且遇到了这个旧帖子。我的解决方案涉及将特定的设备测试命名为以“ 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 }
}