有没有办法在 XCTest 函数中模拟用户的输入?

Posted

技术标签:

【中文标题】有没有办法在 XCTest 函数中模拟用户的输入?【英文标题】:Is there any way to emulate user's input in XCTest function? 【发布时间】:2020-07-02 18:26:02 【问题描述】:

我的方法需要用户输入

@implementation TeamFormation
- (void)run 
    NSFileHandle *kbd = [NSFileHandle fileHandleWithStandardInput];
    NSData *inputData = [kbd availableData];
    NSString *option = [[[NSString alloc] initWithData:inputData
                     encoding:NSUTF8StringEncoding] substringToIndex:1];
    NSLog(@"%@",option);

@end

那我想通过一个测试用例来覆盖这个方法

@interface TeamFormationTests : XCTestCase

@end

@implementation TeamFormationTests

- (void)testTeamFormation 
    TeamFormation *teamFormation = [TeamFormation new];
    [teamFormation run];

    // emulate user's input here


@end

那么,如何在测试用例函数中模拟用户输入?

【问题讨论】:

【参考方案1】:

您有很多选择来实现这一目标。下面两个很明显。

更改 run 以接受参数

- (void)run- (void)runWithFileHandle:(NSFileHandle *)handle 您的应用代码可以传递标准输入文件句柄 您的测试代码可以将句柄传递给具有所需输入的文件

用协议模拟它

创建DataProvider协议:

@protocol DataProvider

@property(readonly, copy) NSData *availableData;

@end

使NSFileHandle符合此协议:

@interface NSFileHandle (AvailableDataProvider) <DataProvider>
@end

TeamFormation上存储一个实现此协议的对象:

@interface TeamFormation : NSObject

@property (nonatomic, nonnull, strong) id<DataProvider> dataProvider;

- (NSString *)run;

@end

默认使用标准输入文件句柄:

@implementation TeamFormation

- (instancetype)init 
    if ((self = [super init]) == nil) 
        return nil;
    
    
    _dataProvider = [NSFileHandle fileHandleWithStandardInput];
    return self;


- (NSString *)run 
    NSData *inputData = [self.dataProvider availableData];
    return [[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding] substringToIndex:1];


@end

在您的测试中创建TestDataProvider

@interface TestDataProvider: NSObject<DataProvider>

@property (nonatomic, strong, nonnull) NSData *dataToProvide;

@end

@implementation TestDataProvider

- (instancetype)init 
    if ((self = [super init]) == nil) 
        return nil;
    
    
    _dataToProvide = [NSData new];
    
    return self;


- (NSData *)availableData 
    return _dataToProvide;


@end

并在TestFormationTests中使用它:

@implementation TeamFormationTests

- (void)testFormationRun 
    TestDataProvider *dataProvider = [TestDataProvider new];
    TeamFormation *formation = [TeamFormation new];
    formation.dataProvider = dataProvider;
    
    XCTAssertThrows([formation run]);
    
    dataProvider.dataToProvide = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
    XCTAssertEqualObjects([formation run], @"f");
    
    dataProvider.dataToProvide = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
    XCTAssertEqualObjects([formation run], @"b");


@end

【讨论】:

谢谢!很酷的答案!

以上是关于有没有办法在 XCTest 函数中模拟用户的输入?的主要内容,如果未能解决你的问题,请参考以下文章

XCTest 中的 Swift 模拟类

在 XCTest 案例中处理对 CLLocationManager 授权的请求

XCTest:有没有办法在 UI 测试中通过 ID 查找任何类型的视图?

iOS:如何在设备上运行 XCTest?

使用 XCTest 运行测试时有没有办法发出警告?

启用和禁用 iCloud 时的 XCTest