测试已测试 | ✓ |
Lang语言 | Obj-CObjective C |
许可证 | Apache 2 |
发布最后发布 | 2015年11月 |
依赖 | |
GRMustache | ~> 7.0 |
KIF | ~> 3.0 |
AMYServer,代表 AMY Mocks Your Server,提供了一种在 KIF 测试用例内对您的 web 服务器进行模拟的机制。
它与 Mocktail 有何区别? Mocktail 在开发过程中很有用,可以排除服务器这一因素,但它有一些限制,可能会影响测试。
AMYServer 通过创建代表您的服务器的 KIF 测试演员来解决这些问题。通过一点设置,您的测试将发展成一个逻辑故事,您可以真正了解您的系统在做什么。
[tester enterText:@"brian" intoViewWithAccessibilityLabel:@"Username"];
[tester enterText:@"$ecret" intoViewWithAccessibilityLabel:@"Password"];
[myServer waitForLoginWithUsername:@"brian" password:@"$ecret"
andRespondWithSuccess:YES message:@"Welcome, Brian" token:@"12345"];
[tester waitForViewWithAccessibilityLabel:@"Welcome, Brian"];
AMYServer 还与 Mocktail 集成,简化了设置新测试的过程。如果您有现有的 tail 文件,您可以只需几行代码就将其集成。
AMYServer 包含一些测试用例以验证其功能。启动测试用例以查看 AMYServer 通过几个标准情况。
可以使用CocoaPods安装 AMYServer。
target 'Acceptance Tests' do
pod 'AMYServer', '~> 2.0'
end
此示例假设您已经熟悉 KIF 2.0 和 Mocktail。
第一步是定义您的服务器及其使用的 API。
ExampleServer.h
#import "AMYServer.h"
#define exampleServer KIFActorWithClass(ExampleServer) // (3)
@interface ExampleServer : AMYServer // (1)
- (void)waitForLoginAndRespondWithMessage:(NSString *)message
token:(NSString *)token; // (2)
@end
AMYServer
实例。tester
。ExampleServer.m
#import "ExampleServer.h"
@implementation ExampleServer
- (NSURL *)baseURL
{
return [NSURL URLWithString:@"https://example.com/services/"]; // (1)
}
- (void)waitForLoginAndRespondWithMessage:(NSString *)message
token:(NSString *)token
{
[self waitForRequestMatchingMocktail:@"successful-login"
andRespondWithValues:@{@"token": token ?: @"", @"message": message ?: @""}]; // (2)
}
@end
successful-login.tail
POST
login.json
200
application/json
{
"success": true,
"message": "{{{message}}}",
"token": "{{{token}}}"
}
定义您的 Mocktail 并将其包含在测试目标中。
配置完成后,您可以编写一个使用它的测试用例。
LoginTests.m
#import <KIFTestCase.h>
#import "ExampleServer.h"
@interface AMYServerTests : KIFTestCase
@end
@implementation AMYServerTests
- (void)beforeAll
{
[exampleServer start]; // (1)
}
- (void)afterAll
{
[exampleServer stop]; // (5)
}
- (void)testSuccessfulLogin
{
[tester tapViewWithAccessibilityLabel:@"Log In"]; // (2)
[exampleServer waitForLoginAndRespondWithMessage:@"Welcome, Brian" token:@"12345"]; // (3)
[tester waitForViewWithAccessibilityLabel:@"Welcome, Brian"]; // (4)
}
@end
AMYServer提供了一些基于鸡尾酒的功能。
利用这些功能,我们可以增强登录测试步骤,以验证用户名和密码,并在响应中注入自定义头。
ExampleServer.m
- (void)waitForLoginWithUsername:(NSString *)username
password:(NSString *)password
andRespondWithMessage:(NSString *)message
token:(NSString *)token
{
[self waitForRequestMatchingMocktail:@"successful-login"
withHTTPBodyMatchingBlock:^KIFTestStepResult(NSData *body, NSError *__autoreleasing *error) {
id json = [NSJSONSerialization JSONObjectWithData:body options:0 error:NULL];
KIFTestWaitCondition([json[@"username"] isEqualToString:username], error, @"Could not find username");
KIFTestWaitCondition([json[@"password"] isEqualToString:password], error, @"Could not find password");
return KIFTestStepResultSuccess;
}
andRespondWithValues:@{@"token": token ?: @"", @"message": message ?: @""}];
}
@end
在这种情况下,AMYServer将忽略不具有正确用户名和密码的请求,并提供一个有意义的结果。
successful-login.tail
POST
login.json
200
application/json
X-Application-Token: {{{token}}}
{
"success": true,
"message": "{{{message}}}",
"token": "{{{token}}}"
}
在这里,AMYServer注入了一个包含令牌的自定义头。
与其每次渲染模板时都提供所有值,AMYServer 允许您提供一个带有默认值的 JSON 文件。该文件的名称与尾部文件相同,但有一个额外的扩展名 .defaults.json
。
successful-login.tail.defaults.json
{ "message": "Good morning, sir", "token": "1234" }
AMYServer不仅限于鸡尾酒。它可以用来按每次 1000 字节、每 5 秒发送一个字节的方式服务图片。
- (void)waitForImageRequestAndRespondPainfully
{
AMYRequest *request = [self waitForRequestMatchingBlock:^KIFTestStepResult(NSURLRequest *request, NSError **error) {
KIFTestWaitCondition([request.URL.lastPathComponent isEqualToString:@"image.do"], error, @"Could not find request for image.do");
return KIFTestStepResultSuccess;
}];
[request respondWithSatusCode:200 headerFields:@{@"Content-Size": @"1000000"}];
while (!done) {
[request sendData:moreData];
[self waitForTimeInterval:5];
}
[request close];
}
首先我们等待匹配我们想要规则的请求。在这种情况下,最后一个路径组件应该是 "image.do"。然后我们发送响应头,并缓慢构建正文,最后关闭。这里重要的是,我们可以在数据返回的同时执行任何我们想要的操作。