用于基于方法选择器字符串对非 UI 流进行单元测试的 pod。
当为应用程序的非 UI 部分编写单元测试时,例如某种类型的内存中本地存储,对于某些可能有多种方式到达相同最终结果的场景,基本的单元测试可能是不够的。因此,尽管单元测试通过了,但可能只测试了一条路线,而其他也可能给出相同结果的路线并没有被测试。这个 pod 帮助明确覆盖其他路径。
flow-test
明确指出了对特定测试而言,必须按特定顺序调用某些方法列表,以便测试成功。
这意味着您不会像对待黑盒一样对待您的 API。因此,这对于实现流程并确保它不会在未来更改中失效的人来说特别有用 :)
您可以使用 Cocoapods 通过将以下内容添加到 podfile 中的测试目标来安装 flow-test
-
pod 'flow-test'
因此,您应用程序名为 MyApp
的最终测试目标将看起来像这样 -
target 'MyApp_Tests' do
inherit! :search_paths
pod 'flow-test'
end
假设您有一个逻辑流程看起来像这样 -
@implementation MyFeature
- (NSUInteger)complicatedFeature:(NSUInteger)index{
if(index == 0){
[self callSampleMethod];
}
return 42
}
- (void)callSampleMethod{
// ... Some more code here.
}
@end
MyFeature
是一个类,它包含一个 complicatedFeature
方法,该方法根据传入的参数调用不同的方法,尽管它每次都返回相同的响应。
所以我们用参数 0
和 1
测试 complicatedFeature
的流程。请注意,当传入的参数为 0
时,将调用 callSampleMethod
方法。我们可以断言这一点。
最终的测试将看起来像这样 -
@import flow_test;
#import "MyFeature.h"
@interface MyFeatureTests : KMFTestManager
@end
@implementation MyFeatureTests
/// Note that the flow-test starts with `testFlow`
- (void)testFlowFeatureWithZero{
// Add the class-name and the method-name that will be
// encountered when calling `complicatedFeature`.
KMFAddMethodSpecsList((@[
KMFMakeMethodSpec(@"MyFeature", @"callSampleMethod")
]));
// Regular tests from here on
MyFeature *featureObj = [[MyFeature alloc] init];
NSUInteger result = [featureObj complicatedFeature:0];
XCTAssert(result == 42);
}
- (void)testFlowFeatureWithNonZero{
MyFeature *featureObj = [[MyFeature alloc] init];
NSUInteger result = [featureObj complicatedFeature:0];
XCTAssert(result == 42);
}
@end
让我们来分解一下 -
您可以使用 @import
导入 pod,并且与您的测试扩展从 XCTestCase
不同,您将使用 KMFTestManager
类。
@import flow_test;
@interface MyFeatureTests : KMFTestManager
...
@end
当测试方法流时,请确保测试名称以 testFlow
开始。如果不是,这些测试中的方法将不会进行断言,并且它们将像正常运行 XCTestCase
一样工作。
可以使用类名和方法选择器字符串来指定方法。这内部称为方法规范。您可以使用宏 KMFMakeMethodSpec(@"classname", @"methodSelector")
创建方法规范。
您可以将一系列方法规范添加到断言这些选择器将按列表中指定的顺序调用。您需要将方法规范列表添加到 KMFAddMethodSpecsList((@[...]))
中。注意额外的括号。这样做是为了使宏接受数组作为单一参数,并不会被拆包。如果您愿意,可以将数组分配给另一个变量并将其传递给宏 :)
因此,complicatedFeature
的 flow-test 将看起来像这样 -
- (void)testFlowFeatureWithZero{
// Add the class-name and the method-name that will be
// encountered when calling `complicatedFeature`.
KMFAddMethodSpecsList((@[
KMFMakeMethodSpec(@"MyFeature", @"callSampleMethod")
// You can add more method-specs here
]));
// Regular XCTestCase assertions from this point...
}
就这样了!
您可以将多个条目添加到列表中,test-flow
将检查这些方法是否已按列表中指定的顺序调用。
请注意,这并不意味着,只有这些方法需要被调用!其他方法也可以被调用,只要调用了方法规格列表中指定的方法,测试就会成功。
- (void)testFlowFeatureWithMultipleMethods{
// This asserts that first callSampleMethod will be called, followed by callMethod1 and callMethod2
KMFAddMethodSpecsList((@[
KMFMakeMethodSpec(@"MyFeature", @"callSampleMethod"),
KMFMakeMethodSpec(@"MyFeature", @"callMethod1"),
KMFMakeMethodSpec(@"MyFeature", @"callMethod2"),
]));
// Regular tests from here on...
}
flowMethodSpecsList
方法请注意有一个特殊的方法 - flowMethodSpecsList
,在其中可以指定在当前测试类中多个测试共有的方法规格。
因此,在上面的 MyFeature
类中,如果有一个在所有方法,包括 complicatedFeature
中都会调用的 commonMethod
,那么测试看起来会是这样 -
// The commonMethod is added to the method-specs list before running every test.
- (NSArray<KMFMethodSpec *> *)flowMethodSpecsList{
return @[
KMFMakeMethodSpec(@"MyFeature", @"commonMethod")
];
}
- (void)testFlowFeatureWithZero{
KMFAddMethodSpecsList((@[
KMFMakeMethodSpec(@"MyFeature", @"callSampleMethod")
]));
// ... Rest of the test
}
- (void)testFlowFeatureWithNonZero{
// ... Rest of the test
}
这只是为了让原生测试更简洁。完全可以省略 flowMethodSpecsList
,使用 KMFAddMethodSpecsList()
在每个 testFlow
测试中指定方法规格列表。
flow-test
依赖于,以及由于,神奇的 Aspects
库。
gnithin,[email protected]
flow-test 遵循 MIT 许可协议。有关更多信息,请参阅 LICENSE 文件。