测试已测试 | ✓ |
Lang语言 | Obj-CObjective C |
许可证 | MIT |
发布上次发布 | 2017年6月 |
由Blake Watters,Peter Jihoon Kim,Robert Böhnke,Orta Therox维护。
Objective-C 和 Cocoa 的匹配器框架。
使用 Expecta 相比其他匹配器框架的主要优势是不必指定数据类型。此外,Expecta 匹配器的语法更加易读,且不受括号的限制。
expect(@"foo").to.equal(@"foo"); // `to` is a syntactic sugar and can be safely omitted.
expect(foo).notTo.equal(1);
expect([bar isBar]).to.equal(YES);
expect(baz).to.equal(3.14159);
Expecta 是框架无关的:它与 XCTest 以及与 XCTest 兼容的测试框架(如 Specta 或 Kiwi)配合使用非常好。
expect(x).to.equal(y);
比较对象或基本类型 x 和 y,如果它们是相同的(==)或等效的(isEqual:),则通过。
expect(x).to.beIdenticalTo(y);
比较对象 x 和 y,如果它们是相同的并且具有相同的内存地址,则通过。
expect(x).to.beNil();
如果 x 是 nil,则通过。
expect(x).to.beTruthy();
如果 x 计算为 true(非零),则通过。
expect(x).to.beFalsy();
如果 x 计算为 false(零),则通过。
expect(x).to.contain(y);
如果 NSArray 或 NSString 的实例 x 包含 y,则通过。
expect(x).to.beSupersetOf(y);
如果 NSArray、NSSet、NSDictionary 或 NSOrderedSet 的实例 x 包含 y 的所有元素,则通过。
expect(x).to.haveCountOf(y);
如果 NSArray、NSSet、NSDictionary 或 NSString 的实例 x 的计数或长度为 y,则通过。
expect(x).to.beEmpty();
如果 NSArray、NSSet、NSDictionary 或 NSString 的实例 x 的计数或长度为空,则通过。
expect(x).to.beInstanceOf([Foo class]);
如果 x 是类 Foo 的实例,则通过。
expect(x).to.beKindOf([Foo class]);
如果 x 是类 Foo 的实例,或者 x 是类 Foo 或从类 Foo 继承的任何类的实例,则通过。
expect([Foo class]).to.beSubclassOf([Bar class]);
如果类 Foo 是类 Bar 的子类,或者它与类 Bar 相同,则通过。对于类簇,请使用 beKindOf()。
expect(x).to.beLessThan(y);
如果 x 小于 y,则通过。
expect(x).to.beLessThanOrEqualTo(y);
如果 x 小于或等于 y,则通过。
expect(x).to.beGreaterThan(y);
如果 x 大于 y,则通过。
expect(x).to.beGreaterThanOrEqualTo(y);
如果 x 大于或等于 y,则通过。
expect(x).to.beInTheRangeOf(y,z);
如果 x 在 y 和 z 范围内,则通过。
expect(x).to.beCloseTo(y);
如果 x 接近 y,则通过。
expect(x).to.beCloseToWithin(y, z);
当x
在z
的范围内接近y
时通过。
expect(^{ /* code */ }).to.raise(@"ExceptionName");
如果给定的代码块抛出名为ExceptionName
的异常则通过。
expect(^{ /* code */ }).to.raiseAny();
如果给定的代码块抛出任何异常则通过。
expect(x).to.conformTo(y);
如果x
遵守协议y
则通过。
expect(x).to.respondTo(y);
如果x
能够响应该选择器y
则通过。
expect(^{ /* code */ }).to.notify(@"NotificationName");
如果给定的代码块生成名为NotificationName
的 NSNotification 则通过。
expect(^{ /* code */ }).to.notify(notification);
如果给定的代码块生成的 NSNotification 等于传递的notification
则通过。
expect(x).to.beginWith(y);
如果NSString、NSArray、或NSOrderedSet的实例x
以y
开头则通过。也等价于startWith
。
expect(x).to.endWith(y);
如果NSString、NSArray、或NSOrderedSet的实例x
以y
结尾则通过。
expect(x).to.match(y);
如果NSString的实例x
至少一次匹配正则表达式(以NSString形式给出)y
则通过。
每个匹配器的标准都可以通过在前面添加 .notTo
或 .toNot
来取反。
expect(x).notTo.equal(y);
比较对象或原始值 x 和 y 和如果它们不等价则通过。
可以通过在前面添加 .will
、.willNot
或 after(...)
使每个匹配器执行异步测试。
expect(x).will.beNil();
如果 x 在默认超时前变为 nil 则通过。
expect(x).willNot.beNil();
如果 x 在默认超时前变为非 nil 则通过。
expect(x).after(3).to.beNil();
如果 x 在 3.0 秒后变为 nil 则通过。
expect(x).after(2.5).notTo.equal(42);
如果 x 在 2.5 秒后不等于 42 则通过。
默认超时是 1.0 秒,如果不另行指定则用于所有匹配器。此设置可以通过调用 [Expecta setAsynchronousTestTimeout:x]
来更改,其中 x
是以秒为单位的期望超时。
describe(@"Foo", ^{
beforeAll(^{
// All asynchronous matching using `will` and `willNot`
// will have a timeout of 2.0 seconds
[Expecta setAsynchronousTestTimeout:2];
});
it(@"will not be nil", ^{
// Test case where default timeout is used
expect(foo).willNot.beNil();
});
it(@"should equal 42 after 3 seconds", ^{
// Signle case where timeout differs from the default
expect(foo).after(3).to.equal(42);
});
});
您可以通过使用 failure
属性来使测试失败。这可以用来测试分支。
failure(@"This should not happen");
明确使测试失败。
使用 Expecta 提供的特殊宏编写新的匹配器很容易。查看 .beKindOf()
匹配器是如何定义的。
EXPMatchers+beKindOf.h
#import "Expecta.h"
EXPMatcherInterface(beKindOf, (Class expected));
// 1st argument is the name of the matcher function
// 2nd argument is the list of arguments that may be passed in the function
// call.
// Multiple arguments are fine. (e.g. (int foo, float bar))
#define beAKindOf beKindOf
EXPMatchers+beKindOf.m
#import "EXPMatchers+beKindOf.h"
EXPMatcherImplementationBegin(beKindOf, (Class expected)) {
BOOL actualIsNil = (actual == nil);
BOOL expectedIsNil = (expected == nil);
prerequisite(^BOOL {
return !(actualIsNil || expectedIsNil);
// Return `NO` if matcher should fail whether or not the result is inverted
// using `.Not`.
});
match(^BOOL {
return [actual isKindOfClass:expected];
// Return `YES` if the matcher should pass, `NO` if it should not.
// The actual value/object is passed as `actual`.
// Please note that primitive values will be wrapped in NSNumber/NSValue.
});
failureMessageForTo(^NSString * {
if (actualIsNil)
return @"the actual value is nil/null";
if (expectedIsNil)
return @"the expected value is nil/null";
return [NSString
stringWithFormat:@"expected: a kind of %@, "
"got: an instance of %@, which is not a kind of %@",
[expected class], [actual class], [expected class]];
// Return the message to be displayed when the match function returns `YES`.
});
failureMessageForNotTo(^NSString * {
if (actualIsNil)
return @"the actual value is nil/null";
if (expectedIsNil)
return @"the expected value is nil/null";
return [NSString
stringWithFormat:@"expected: not a kind of %@, "
"got: an instance of %@, which is a kind of %@",
[expected class], [actual class], [expected class]];
// Return the message to be displayed when the match function returns `NO`.
});
}
EXPMatcherImplementationEnd
可以通过简单地定义匹配器接口将谓词匹配器添加进来,匹配器实现将在运行时通过将对象上的谓词方法委托来处理。
例如,如果您有以下类
@interface LightSwitch : NSObject
@property (nonatomic, assign, getter=isTurnedOn) BOOL turnedOn;
@end
@implementation LightSwitch
@synthesize turnedOn;
@end
编写一个断言来检查开关是否打开的常规方式
expect([lightSwitch isTurnedOn]).to.beTruthy();
但是,如果我们定义一个自定义谓词匹配器
EXPMatcherInterface(isTurnedOn, (void));
(注意:我们尚未定义匹配器实现,只是它的接口)
现在,您可以按照以下方式编写您的断言
expect(lightSwitch).isTurnedOn();
您可以使用 CocoaPods、Carthage 或 完全手动 安装 Expecta。
从GitHub克隆Expecta。
在您的项目目录中运行rake
以构建框架和库。
如果您还没有,请向您的Xcode项目添加一个Cocoa或Cocoa Touch单元测试目标。
对于OS X项目,将Expecta.framework
复制并添加到项目的测试目标中的Products/osx
文件夹。
对于iOS项目,将Expecta.framework
复制并添加到项目的测试目标中的Products/ios
文件夹。
如果您更喜欢将Expecta链接为一个静态库,则可以使用libExpecta.a
— iOS 7.x以下版本需要这样做。
将-ObjC
和-all_load
添加到Xcode项目中测试目标的其他链接器标志构建设置中。
现在,您可以通过添加以下导入来在测试类中使用Expecta
@import Expecta; // If you're using Expecta.framework
// OR
#import <Expecta/Expecta.h> // If you're using the static library, or the framework
Expecta和Specta被认为是完成的项目,目前没有计划进行活跃开发,除了确保与未来Xcode的兼容性。因此,它是一个稳定的依赖项,但不会进入Swift世界。如果您正在寻找那个,我们建议您考虑Quick和Nimble。
_
)作为实例变量名称的前缀。EXP
作为全局作用域中定义的自定义类和函数的前缀。