我有一些接口(协议)的两个或更多实现:
protocol Interface {
func methodOne()
func methodTwo()
}
我想测试每个实现,但我不想复制代码。我有几个选择,但没有一个让我满意。
首先是为ImplementationA
创建测试用例并将其子类化以获取ImplementationB
的测试用例:
class ImplementationATests: XCTestCase {
var implToTest: Interface!
override func setUp() {
super.setUp()
implToTest = ImplementationA()
}
func testMethodOne() {
...
}
func testMethodTwo() {
...
}
}
class ImplementationBTests: ImplementationATests {
override func setUp() {
super.setUp()
implToTest = ImplementationB()
}
}
这种方法的一个缺点是我无法进行仅适用于ImplementationA
的测试。 (例如,测试一些特定于该实现的辅助方法)
我提出的第二个选项是为测试用例创建共享子类:
class InterfaceTests: XCTestCase {
var implToTest: Interface!
func testMethodOne() {
...
}
func testMethodTwo() {
...
}
}
但是这些测试也将在这里执行,并且它们将失败,因为没有为implToTest
分配实现。当然我可以为它分配一些实现,但接下来我将以相同实现的两个测试用例结束。最好的选择是以某种方式禁用InterfaceTests
测试用例并仅运行其子类。有可能吗?
我得到的第三个想法可能看起来很棘手,但它会满足我的所有需求。不幸的是它没有用。
我决定创建InterfaceTestable
协议:
protocol InterfaceTestable {
var implToTest: Interface! { get set }
}
并使用所有共享测试对其进行扩展:
extension InterfaceTestable {
func testMethodOne() {
...
}
func testMethodTwo() {
...
}
}
然后为每个实现创建测试用例:
class ImplementationATests: XCTestCase, InterfaceTestable {
var implToTest: Interface!
override func setUp() {
super.setUp()
implToTest = ImplementationA()
}
// some tests which only apply to ImplementationA
}
class ImplementationBTests: XCTestCase, InterfaceTestable {
var implToTest: Interface!
override func setUp() {
super.setUp()
implToTest = ImplementationB()
}
// some tests which only apply to ImplementationB
}
这些测试用例编译但Xcode没有看到在InterfaceTestable
扩展名中声明的测试。
还有其他方法可以为不同的实现进行共享测试吗?
答案 0 :(得分:3)
我遇到了同样的问题并使用您的第二个选项解决了它。 但是,我找到了一种方法来防止基类的测试用例运行:
重写基类中的defaultTestSuite()
类方法以返回空XCTestSuite
:
class InterfaceTests: XCTestCase {
var implToTest: Interface!
override class func defaultTestSuite() -> XCTestSuite {
return XCTestSuite(name: "InterfaceTests Excluded")
}
}
这样就不会运行InterfaceTests
的测试。不幸的是,也没有ImplementationATests
的测试。通过覆盖defaultTestSuite()
中的ImplementationATests
,可以解决这个问题:
class ImplementationATests : XCTestCase {
override func setUp() {
super.setUp()
implToTest = ImplementationA()
}
override class func defaultTestSuite() -> XCTestSuite {
return XCTestSuite(forTestCaseClass: ImplementationATests.self)
}
}
现在ImplementationATests
的测试套件将运行InterfaceTests
的所有测试,但不会直接运行InterfaceTests
的测试,而不会设置implToTest
。
答案 1 :(得分:1)
我之前使用共享基类的方式。使implToTest
nillable。在基类中,如果没有提供实现,只需在保护条款中进行测试return
。
测试运行包括基类测试的报告,当它没有做任何事情时,这有点令人讨厌。但这是一个小烦恼。测试子类将提供有用的反馈。