Expecta 1.0.6

Expecta 1.0.6

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布上次发布2017年6月

Blake WattersPeter Jihoon KimRobert BöhnkeOrta Therox维护。



Expecta 1.0.6

  • Peter Jihoon Kim

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 兼容的测试框架(如 SpectaKiwi)配合使用非常好。

匹配器

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);xz 的范围内接近 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的实例 xy 开头则通过。也等价于 startWith

expect(x).to.endWith(y); 如果NSString、NSArray、或NSOrderedSet的实例 xy 结尾则通过。

expect(x).to.match(y); 如果NSString的实例 x 至少一次匹配正则表达式(以NSString形式给出)y 则通过。

取反匹配器

每个匹配器的标准都可以通过在前面添加 .notTo.toNot 来取反。

expect(x).notTo.equal(y); 比较对象或原始值 x 和 y 和如果它们不等价则通过。

异步测试

可以通过在前面添加 .will.willNotafter(...) 使每个匹配器执行异步测试。

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。

手动设置

  1. 从GitHub克隆Expecta。

  2. 在您的项目目录中运行rake以构建框架和库。

  3. 如果您还没有,请向您的Xcode项目添加一个Cocoa或Cocoa Touch单元测试目标。

  4. 对于OS X项目,将Expecta.framework复制并添加到项目的测试目标中的Products/osx文件夹。

    对于iOS项目,将Expecta.framework复制并添加到项目的测试目标中的Products/ios文件夹。

    如果您更喜欢将Expecta链接为一个静态库,则可以使用libExpecta.a — iOS 7.x以下版本需要这样做。

  5. -ObjC-all_load添加到Xcode项目中测试目标的其他链接器标志构建设置中。

  6. 现在,您可以通过添加以下导入来在测试类中使用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世界。如果您正在寻找那个,我们建议您考虑QuickNimble

贡献指南

  • 请只使用空格,每次缩进2个空格。
  • 请以单个下划线(_)作为实例变量名称的前缀。
  • 请以EXP作为全局作用域中定义的自定义类和函数的前缀。

许可证

版权所有 (c) 2012-2016 Specta团队。本软件受MIT许可证许可。