Expecta
Objective-C 和 Cocoa 的匹配器框架。
特性
使用 Expecta 而不是其他匹配器框架的主要优点是您不必指定数据类型。 此外,Expecta 匹配器的语法更具可读性,并且不会出现括号内容。
expect(@"foo").to.equal(@"foo"); // `to` 是一种语法糖,可以安全地省略。 expect(foo).notTo.equal(1); expect([bar isBar]).to.equal(YES); expect(baz).to.equal(3.14159);
Expecta 与框架无关:它可以与 XCTest 和兼容 XCTest 的测试框架(如 Specta 或 Kiwi )很好地工作。
MATCHERS
expect(x).to.equal(y);
compares objects or primitives x and y and passes if they are identical (==) or equivalent isEqual:).
expect(x).to.beIdenticalTo(y);
compares objects x and y and passes if they are identical and have the same memory address.
expect(x).to.beNil();
passes if x is nil.
expect(x).to.beTruthy();
passes if x evaluates to true (non-zero).
expect(x).to.beFalsy();
passes if x evaluates to false (zero).
expect(x).to.contain(y);
passes if an instance of NSArray or NSString x contains y.
expect(x).to.beSupersetOf(y);
passes if an instance of NSArray, NSSet, NSDictionary or NSOrderedSet x contains all elements of y.
expect(x).to.haveCountOf(y);
passes if an instance of NSArray, NSSet, NSDictionary or NSString x has a count or length of y.
expect(x).to.beEmpty();
passes if an instance of NSArray, NSSet, NSDictionary or NSString x has a count or length of .
expect(x).to.beInstanceOf([Foo class]);
passes if x is an instance of a class Foo.
expect(x).to.beKindOf([Foo class]);
passes if x is an instance of a class Foo or if x is an instance of any class that inherits from the class Foo.
expect([Foo class]).to.beSubclassOf([Bar class]);
passes if the class Foo is a subclass of the class Bar or if it is identical to the class Bar. Use beKindOf() for class clusters.
expect(x).to.beLessThan(y);
passes ifx
is less thany
.
expect(x).to.beLessThanOrEqualTo(y);
passes ifx
is less than or equal toy
.
expect(x).to.beGreaterThan(y);
passes ifx
is greater thany
.
expect(x).to.beGreaterThanOrEqualTo(y);
passes ifx
is greater than or equal toy
.
expect(x).to.beInTheRangeOf(y,z);
passes ifx
is in the range ofy
andz
.
expect(x).to.beCloseTo(y);
passes ifx
is close toy
.
expect(x).to.beCloseToWithin(y, z);
passes ifx
is close toy
withinz
.
expect(^{ /* code */ }).to.raise(@"ExceptionName");
passes if a given block of code raises an exception namedExceptionName
.
expect(^{ /* code */ }).to.raiseAny();
passes if a given block of code raises any exception.
expect(x).to.conformTo(y);
passes ifx
conforms to the protocoly
.
expect(x).to.respondTo(y);
passes ifx
responds to the selectory
.
expect(^{ /* code */ }).to.notify(@"NotificationName");
passes if a given block of code generates an NSNotification namedNotificationName
.
expect(^{ /* code */ }).to.notify(notification);
passes if a given block of code generates an NSNotification equal to the passednotification
.
expect(x).to.beginWith(y);
passes if an instance of NSString, NSArray, or NSOrderedSetx
begins withy
. Also liased bystartWith
expect(x).to.endWith(y);
passes if an instance of NSString, NSArray, or NSOrderedSetx
ends withy
.
expect(x).to.match(y);
passes if an instance of NSStringx
matches regular expression (given as NSString)y
one or more times.
Inverting Matchers
Every matcher's criteria can be inverted by prepending .notTo
or .toNot
:
expect(x).notTo.equal(y);
compares objects or primitives x and y and passes if they are not equivalent.
Asynchronous Testing
Every matcher can be made to perform asynchronous testing by prepending .will
, .willNot
or after(...)
:
expect(x).will.beNil();
passes if x becomes nil before the default timeout.
expect(x).willNot.beNil();
passes if x becomes non-nil before the default timeout.
expect(x).after(3).to.beNil();
passes if x becoms nil after 3.0 seconds.
expect(x).after(2.5).notTo.equal(42);
passes if x doesn't equal 42 after 2.5 seconds.
默认超时为1.0秒,如果没有另外指定,则用于所有匹配器。 可以通过调用 [Expecta setAsynchronousTestTimeout:x]
, 来更改此设置,其中x
是所需的超时(秒)。
", ^{ beforeAll(^{ // All asynchronous matching using `will` and `willNot` // will have a timeout of 2.0 seconds [Expecta 2]; }); ", ^{ // Test case where default timeout is used beNil(); }); ", ^{ // Signle case where timeout differs from the default 42); }); });
Forced Failing
You can fail a test by using the failure
attribute. This can be used to test branching.
failure(@"This should not happen");
outright fails a test.
WRITING NEW MATCHERS
使用Expecta提供的特殊宏可以轻松编写新的匹配器。 看看如何定义 .beKindOf()
匹配器:
EXPMatchers+beKindOf.h
#" 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)) #beAKindOf beKindOf
EXPMatchers+beKindOf.m
#" Class expected)) { nil); nil); BOOL { return !(actualIsNil || expectedIsNil); // Return `NO` if matcher should fail whether or not the result is inverted // using `.Not`. }); BOOL { 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. }); NSString * { if (actualIsNil) "; if (expectedIsNil) "; NSString " ", [expected class]]; // Return the message to be displayed when the match function returns `YES`. }); NSString * { if (actualIsNil) "; if (expectedIsNil) "; NSString " ", [expected class]]; // Return the message to be displayed when the match function returns `NO`. }); } EXPMatcherImplementationEnd
DYNAMIC PREDICATE MATCHERS
可以通过简单地定义匹配器接口来添加谓词匹配器,并通过委托对象的谓词方法在运行时处理匹配器实现。
例如,如果您有以下类:
NSObject BOOL turnedOn; @end LightSwitch @synthesize turnedOn; @end
写一个开关打开的断言的正常方法是:
expect([lightSwitch isTurnedOn]).to.beTruthy();
但是,如果我们定义自定义谓词匹配器:
EXPMatcherInterface(isTurnedOn, (void));
(注意:我们还没有定义匹配器实现,只是它的界面)
您现在可以按如下方式编写断言:
expect(lightSwitch).isTurnedOn();