简体   繁体   English

XCTest 测试套件中的共享测试

[英]Shared tests in XCTest test suites

I have a class which can be configured to do 2 slightly different things.我有一个类,它可以配置为做 2 件稍微不同的事情。 I want to test both paths.我想测试两条路径。 The class is a descendant of UIViewController and most of the configuration takes place in Interface Builder.该类是UIViewController的后代,大部分配置发生在 Interface Builder 中。 i need to verify that both Storyboard Scenes and their Outlets are wired up in the same way, but also need to check for the difference in behavior.我需要验证故事板场景和它们的插座是否以相同的方式连接,但还需要检查行为的差异。

I'd like to use shared XCTest suites for this purpose.为此,我想使用共享的 XCTest 套件。

One is aimed for use with the left hand, one for the right.一种用于左手,一种用于右手。 Both appear after another when using the app.使用该应用程序时,两者都会出现。 The first one (right hand) triggers a segue to the other.第一个(右手)触发到另一个的转场。 The last one (left hand) should trigger a different segue.最后一个(左手)应该触发不同的转场。 This is where it differs, for example.例如,这就是它不同的地方。

Now I want to verify the segues with tests.现在我想通过测试来验证 segue。 I'd like to create a BothHandSharedTests suite which both view controller instance tests use to verify everything they have in common.我想创建一个BothHandSharedTests套件,两个视图控制器实例测试都使用它来验证它们的所有共同点。 However, the BothHandSharedTests class is treated as a self-containing test suite, which it clearly isn't.然而, BothHandSharedTests类被视为一个自包含的测试套件,它显然不是。

I came up with these strategies:我想出了这些策略:

  • inherit from an abstract XCTest descendant, like described above (doesn't seem to be that easy),从抽象的 XCTest 后代继承,如上所述(似乎并不那么容易),
  • write a test auite for the common properties and use one of the two as the Object Under Test, and add two smaller suites for the differences.为公共属性编写一个测试套件,并使用两者之一作为测试对象,并为差异添加两个较小的套件。

How would you solve this problem?你会如何解决这个问题?

Here's a solution in Swift:这是 Swift 中的解决方案:

class AbstractTests: XCTestCase {

    // Your tests here

    override func perform(_ run: XCTestRun) {
        if type(of: self) != AbstractTests.self {
            super.perform(run)
        }
    }
}

I don't have a conclusive answer, but here's what I ended up doing.我没有结论性的答案,但这是我最终做的。

I first tried the subclassing route.我首先尝试了子类化路线。 In the parent test (the "AbstractTestCase") I implemented all the tests that would be executed by the the AbstractTestCase subclasses, but added a macro so they don't get run by the actual parent test:在父测试(“AbstractTestCase”)中,我实现了所有将由 AbstractTestCase 子类执行的测试,但添加了一个宏,因此它们不会被实际的父测试运行:

#define DONT_RUN_TEST_IF_PARENT if ([[self className] isEqualToString:@"AbstractTestCase"]) { return; }

I then added this macro to the start of every test, like so:然后我将此宏添加到每个测试的开头,如下所示:

- (void)testSomething
{
    DONT_RUN_TEST_IF_PARENT

    ... actual test code ...
}

This way, in the ConcreteTestCase classes which inherit from AbstractTestCase, all those tests would be shared and run automatically.这样,在继承自 AbstractTestCase 的 ConcreteTestCase 类中,所有这些测试都将共享并自动运行。 You can override -setUp to perform the necessary class-specific set-up, of course.当然,您可以覆盖 -setUp 以执行必要的特定于类的设置。

However – This turned out to be a crappy solution for a couple reasons:然而——结果证明这是一个糟糕的解决方案,原因有几个:

  1. It confuses Xcodes testing UI.它混淆了 Xcodes 测试 UI。 You don't really get to see a live representation of what's running, and tests sometimes don't show up as intended.您无法真正看到正在运行的内容的实时表示,并且测试有时不会按预期显示。 This makes clicking through to debug test failures difficult or impossible.这使得点击调试测试失败变得困难或不可能。
  2. It confuses XCTest itself – I found that tests would often get run even when I didn't ask them too (if I were just trying to run a single test) and the so the test output wouldn't be what I would expect.它混淆了 XCTest 本身——我发现即使我没有问他们,测试也经常会运行(如果我只是试图运行一个测试),所以测试输出不会是我所期望的。
  3. Honestly it felt a little janky to have that macro – macros which redirect flow control are never really that good of an idea.老实说,拥有那个宏感觉有点笨拙——重定向流控制的宏从来都不是一个好主意。

Instead, I'm now using a shared object, a TestCaseHelper , which is instantiated for each test class, and has has a protocol/delegate pattern common to all test cases.相反,我现在使用共享对象TestCaseHelper ,它为每个测试类实例化,并且具有所有测试用例通用的协议/委托模式。 It's less DRY – most test cases are just duplicates of the others – but at least they are simple.它不那么枯燥——大多数测试用例只是其他测试用例的重复——但至少它们很简单。 This way, Xcode doesn't get confused, and debugging failures is still possible.这样,Xcode 就不会被混淆,调试失败仍然是可能的。

A better solution will likely have to come from Apple, unless you're interested in ditching your entire test suite for something else.更好的解决方案可能必须来自 Apple,除非您有兴趣放弃整个测试套件以换取其他东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM