Merge pull request #43 from jeffh/beTrue-beFalse-matchers

Refactored BeLogical. Added beTrue() and beFalse() matchers. Closes #24
This commit is contained in:
Jeff Hui 2014-10-29 01:17:42 -07:00
Родитель 25bbd061de aa70daa449
Коммит b5cb2a792d
11 изменённых файлов: 256 добавлений и 62 удалений

Просмотреть файл

@ -7,7 +7,7 @@ public struct Expectation<T> {
CurrentAssertionHandler.assert(pass, message: message, location: expression.location)
}
func toImpl<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
public func to<U where U: Matcher, U.ValueType == T>(matcher: U) {
var msg = FailureMessage()
let pass = matcher.matches(expression, failureMessage: msg)
if msg.actualValue == "" {
@ -16,7 +16,7 @@ public struct Expectation<T> {
verify(pass, msg.stringValue())
}
func toNotImpl<U where U: Matcher, U.ValueType == T>(matcher: U) {
public func toNot<U where U: Matcher, U.ValueType == T>(matcher: U) {
var msg = FailureMessage()
let pass = matcher.doesNotMatch(expression, failureMessage: msg)
if msg.actualValue == "" {
@ -25,8 +25,8 @@ public struct Expectation<T> {
verify(pass, msg.stringValue())
}
func notToImpl<U where U: Matcher, U.ValueType == T>(matcher: U) {
toNotImpl(matcher)
public func notTo<U where U: Matcher, U.ValueType == T>(matcher: U) {
toNot(matcher)
}
// see FullMatcherWrapper and AsyncMatcherWrapper for extensions

Просмотреть файл

@ -1,55 +1,73 @@
import Foundation
public struct _BeBooleanTypeMatcher: BasicMatcher {
public let expectedValue: BooleanType
public let stringValue: String
public func matches(actualExpression: Expression<BooleanType>, failureMessage: FailureMessage) -> Bool {
failureMessage.postfixMessage = "be \(stringValue)"
return actualExpression.evaluate()?.boolValue == expectedValue.boolValue
}
}
public struct _BeBoolMatcher: BasicMatcher {
public let expectedValue: BooleanType
public let stringValue: String
public func matches(actualExpression: Expression<Bool>, failureMessage: FailureMessage) -> Bool {
func _beBool(#expectedValue: BooleanType, #stringValue: String, #falseMatchesNil: Bool) -> MatcherFunc<BooleanType> {
return MatcherFunc { actualExpression, failureMessage in
failureMessage.postfixMessage = "be \(stringValue)"
let actual = actualExpression.evaluate()
return (actual?.boolValue) == expectedValue.boolValue
if expectedValue {
return actual?.boolValue == expectedValue.boolValue
} else if !falseMatchesNil {
return actual != nil && actual!.boolValue != !expectedValue.boolValue
} else {
return actual?.boolValue != !expectedValue.boolValue
}
}
}
public func beTruthy() -> _BeBooleanTypeMatcher {
return _BeBooleanTypeMatcher(expectedValue: true, stringValue: "truthy")
// mark: beTrue() / beFalse()
public func beTrue() -> MatcherFunc<Bool> {
return equal(true).withFailureMessage { failureMessage in
failureMessage.postfixMessage = "be true"
}
}
public func beFalsy() -> _BeBooleanTypeMatcher {
return _BeBooleanTypeMatcher(expectedValue: false, stringValue: "falsy")
public func beFalse() -> MatcherFunc<Bool> {
return equal(false).withFailureMessage { failureMessage in
failureMessage.postfixMessage = "be false"
}
}
public func beTruthy() -> _BeBoolMatcher {
return _BeBoolMatcher(expectedValue: true, stringValue: "truthy")
// mark: beTruthy() / beFalsy()
public func beTruthy() -> MatcherFunc<BooleanType> {
return _beBool(expectedValue: true, stringValue: "truthy", falseMatchesNil: true)
}
public func beFalsy() -> _BeBoolMatcher {
return _BeBoolMatcher(expectedValue: false, stringValue: "falsy")
public func beFalsy() -> MatcherFunc<BooleanType> {
return _beBool(expectedValue: false, stringValue: "falsy", falseMatchesNil: true)
}
extension NMBObjCMatcher {
public class func beTruthyMatcher() -> NMBObjCMatcher {
return NMBObjCMatcher { actualBlock, failureMessage, location in
let block = ({ (actualBlock() as? NSNumber)?.boolValue ?? false })
let block = ({ (actualBlock() as? NSNumber)?.boolValue ?? false as BooleanType? })
let expr = Expression(expression: block, location: location)
return beTruthy().matches(expr, failureMessage: failureMessage)
}
}
public class func beFalsyMatcher() -> NMBObjCMatcher {
return NMBObjCMatcher { actualBlock, failureMessage, location in
let block = ({ (actualBlock() as? NSNumber)?.boolValue ?? false })
let block = ({ (actualBlock() as? NSNumber)?.boolValue ?? false as BooleanType? })
let expr = Expression(expression: block, location: location)
return beFalsy().matches(expr, failureMessage: failureMessage)
}
}
public class func beTrueMatcher() -> NMBObjCMatcher {
return NMBObjCMatcher { actualBlock, failureMessage, location in
let block = ({ (actualBlock() as? NSNumber)?.boolValue as Bool? })
let expr = Expression(expression: block, location: location)
return beTrue().matches(expr, failureMessage: failureMessage)
}
}
public class func beFalseMatcher() -> NMBObjCMatcher {
return NMBObjCMatcher { actualBlock, failureMessage, location in
let block = ({ (actualBlock() as? NSNumber)?.boolValue as Bool? })
let expr = Expression(expression: block, location: location)
return beFalse().matches(expr, failureMessage: failureMessage)
}
}
}

Просмотреть файл

@ -2,17 +2,12 @@ import Foundation
// Implement this protocol if you want full control over to() and toNot() behaviors
public protocol Matcher: BasicMatcher {
public protocol Matcher {
typealias ValueType
func matches(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
func doesNotMatch(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
}
// Objective-C interface to a similar interface
@objc public protocol NMBMatcher {
func matches(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
}
// Implement this protocol if you just want a simplier matcher. The negation
// is provided for you automatically.
//
@ -23,6 +18,11 @@ public protocol BasicMatcher {
func matches(actualExpression: Expression<ValueType>, failureMessage: FailureMessage) -> Bool
}
// Objective-C interface to a similar interface
@objc public protocol NMBMatcher {
func matches(actualBlock: () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool
}
// Protocol for types that support contain() matcher
@objc public protocol NMBContainer {
func containsObject(object: AnyObject!) -> Bool

Просмотреть файл

@ -1,6 +1,6 @@
import Foundation
struct AsyncMatcherWrapper<T, U where U: Matcher, U.ValueType == T>: Matcher, BasicMatcher {
struct AsyncMatcherWrapper<T, U where U: Matcher, U.ValueType == T>: Matcher {
let fullMatcher: U
let timeoutInterval: NSTimeInterval = 1
let pollInterval: NSTimeInterval = 0.01
@ -21,23 +21,37 @@ struct AsyncMatcherWrapper<T, U where U: Matcher, U.ValueType == T>: Matcher, Ba
}
extension Expectation {
public func toEventually<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
toImpl(AsyncMatcherWrapper(
fullMatcher: FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
public func toEventually<U where U: Matcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
to(AsyncMatcherWrapper(
fullMatcher: matcher,
timeoutInterval: timeout,
pollInterval: pollInterval))
}
public func toEventuallyNot<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
toNotImpl(AsyncMatcherWrapper(
fullMatcher: FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
public func toEventuallyNot<U where U: Matcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
toNot(AsyncMatcherWrapper(
fullMatcher: matcher,
timeoutInterval: timeout,
pollInterval: pollInterval))
}
public func toEventually<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
toEventually(
FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
timeout: timeout,
pollInterval: pollInterval)
}
public func toEventuallyNot<U where U: BasicMatcher, U.ValueType == T>(matcher: U, timeout: NSTimeInterval = 1, pollInterval: NSTimeInterval = 0.1) {
toEventuallyNot(
FullMatcherWrapper(
matcher: matcher,
to: "to eventually",
toNot: "to eventually not"),
timeout: timeout,
pollInterval: pollInterval)
}
}

Просмотреть файл

@ -21,11 +21,11 @@ struct FullMatcherWrapper<M, T where M: BasicMatcher, M.ValueType == T>: Matcher
extension Expectation {
public func to<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
toImpl(FullMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"))
to(FullMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"))
}
public func toNot<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {
toNotImpl(FullMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"))
toNot(FullMatcherWrapper(matcher: matcher, to: "to", toNot: "to not"))
}
public func notTo<U where U: BasicMatcher, U.ValueType == T>(matcher: U) {

Просмотреть файл

@ -10,6 +10,14 @@ public struct MatcherFunc<T>: BasicMatcher {
public func matches(actualExpression: Expression<T>, failureMessage: FailureMessage) -> Bool {
return matcher(actualExpression, failureMessage)
}
public func withFailureMessage(postprocessor: (FailureMessage) -> Void) -> MatcherFunc<T> {
return MatcherFunc { actualExpression, failureMessage in
let result = self.matches(actualExpression, failureMessage: failureMessage)
postprocessor(failureMessage)
return result
}
}
}
func _objc(matcher: MatcherFunc<NSObject>) -> NMBObjCMatcher {

Просмотреть файл

@ -64,6 +64,14 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_beFalsy();
NIMBLE_SHORT(id<NMBMatcher> beFalsy(),
NMB_beFalsy());
NIMBLE_EXPORT id<NMBMatcher> NMB_beTrue();
NIMBLE_SHORT(id<NMBMatcher> beTrue(),
NMB_beTrue());
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalse();
NIMBLE_SHORT(id<NMBMatcher> beFalse(),
NMB_beFalse());
NIMBLE_EXPORT id<NMBMatcher> NMB_beNil();
NIMBLE_SHORT(id<NMBMatcher> beNil(),
NMB_beNil());

Просмотреть файл

@ -52,6 +52,14 @@ NIMBLE_EXPORT id<NMBMatcher> NMB_beFalsy() {
return [NMBObjCMatcher beFalsyMatcher];
}
NIMBLE_EXPORT id<NMBMatcher> NMB_beTrue() {
return [NMBObjCMatcher beTrueMatcher];
}
NIMBLE_EXPORT id<NMBMatcher> NMB_beFalse() {
return [NMBObjCMatcher beFalseMatcher];
}
NIMBLE_EXPORT id<NMBMatcher> NMB_beNil() {
return [NMBObjCMatcher beNilMatcher];
}

Просмотреть файл

@ -1,21 +1,142 @@
import XCTest
import Nimble
class BeLogicalTest: XCTestCase {
func testBeTruthy() {
enum ConvertsToBool : BooleanType, Printable {
case TrueLike, FalseLike
var boolValue : Bool {
switch self {
case .TrueLike: return true
case .FalseLike: return false
}
}
var description : String {
switch self {
case .TrueLike: return "TrueLike"
case .FalseLike: return "FalseLike"
}
}
}
class BeTruthyTest : XCTestCase {
func testShouldMatchTrue() {
expect(true).to(beTruthy())
failsWithErrorMessage("expected <true> to not be truthy") {
expect(true).toNot(beTruthy())
}
}
func testShouldNotMatchFalse() {
expect(false).toNot(beTruthy())
failsWithErrorMessage("expected <false> to be truthy") {
expect(false).to(beTruthy())
}
}
func testBeFalsy() {
expect(false).to(beFalsy())
func testShouldNotMatchNilBools() {
expect(nil as Bool?).toNot(beTruthy())
failsWithErrorMessage("expected <nil> to be truthy") {
expect(nil as Bool?).to(beTruthy())
}
}
func testShouldMatchBoolConvertibleTypesThatConvertToTrue() {
expect(ConvertsToBool.TrueLike).to(beTruthy())
failsWithErrorMessage("expected <TrueLike> to not be truthy") {
expect(ConvertsToBool.TrueLike).toNot(beTruthy())
}
}
func testShouldNotMatchBoolConvertibleTypesThatConvertToFalse() {
expect(ConvertsToBool.FalseLike).toNot(beTruthy())
failsWithErrorMessage("expected <FalseLike> to be truthy") {
expect(ConvertsToBool.FalseLike).to(beTruthy())
}
}
}
class BeTrueTest : XCTestCase {
func testShouldMatchTrue() {
expect(true).to(beTrue())
failsWithErrorMessage("expected <true> to not be true") {
expect(true).toNot(beTrue())
}
}
func testShouldNotMatchFalse() {
expect(false).toNot(beTrue())
failsWithErrorMessage("expected <false> to be true") {
expect(false).to(beTrue())
}
}
func testShouldNotMatchNilBools() {
expect(nil as Bool?).toNot(beTrue())
failsWithErrorMessage("expected <nil> to be true") {
expect(nil as Bool?).to(beTrue())
}
}
}
class BeFalsyTest : XCTestCase {
func testShouldNotMatchTrue() {
expect(true).toNot(beFalsy())
failsWithErrorMessage("expected <true> to be falsy") {
expect(true).to(beFalsy())
}
}
func testShouldMatchFalse() {
expect(false).to(beFalsy())
failsWithErrorMessage("expected <false> to not be falsy") {
expect(false).toNot(beFalsy())
}
}
func testShouldMatchNilBools() {
expect(nil as Bool?).to(beFalsy())
failsWithErrorMessage("expected <nil> to not be falsy") {
expect(nil as Bool?).toNot(beFalsy())
}
}
}
class BeFalseTest : XCTestCase {
func testShouldNotMatchTrue() {
expect(true).toNot(beFalse())
failsWithErrorMessage("expected <true> to be false") {
expect(true).to(beFalse())
}
}
func testShouldMatchFalse() {
expect(false).to(beFalse())
failsWithErrorMessage("expected <false> to not be false") {
expect(false).toNot(beFalse())
}
}
func testShouldNotMatchNilBools() {
failsWithErrorMessage("expected <nil> to be false") {
expect(nil as Bool?).to(beFalse())
}
failsWithErrorMessage("expected <nil> to not be false") {
expect(nil as Bool?).toNot(beFalse())
}
}
}

Просмотреть файл

@ -81,6 +81,18 @@
expect(nil).to(beFalsy());
}
- (void)testBeTrue {
expect(@YES).to(beTrue());
expect(@NO).toNot(beTrue());
expect(nil).toNot(beTrue());
}
- (void)testBeFalse {
expect(@NO).to(beFalse());
expect(@YES).toNot(beFalse());
expect(nil).toNot(beFalse());
}
- (void)testBeNil {
expect(nil).to(beNil());
expect(@NO).toNot(beNil());
@ -121,11 +133,4 @@
expectAction(exception).toNot(raiseException());
}
//- (void)testOneOf {
// expect(@1).to(beOneOf(@1));
// expect(@1).toNot(equal(@2));
// expect(@1).notTo(equal(@2));
// expect(@"hello").to(equal(@"hello"));
//}
@end

Просмотреть файл

@ -520,9 +520,15 @@ expect(dolphin).to(beAKindOf([Mammal class]));
// Passes if actual is not nil, false, or an object with a boolean value of false:
expect(actual).to(beTruthy())
// Passes if actual is only true (not nil or an object conforming to BooleanType true):
expect(actual).to(beTrue())
// Passes if actual is nil, false, or an object with a boolean value of false:
expect(actual).to(beFalsy())
// Passes if actual is only false (not nil or an object conforming to BooleanType false):
expect(actual).to(beFalse())
// Passes if actual is nil:
expect(actual).to(beNil())
```
@ -533,9 +539,15 @@ expect(actual).to(beNil())
// Passes if actual is not nil, false, or an object with a boolean value of false:
expect(actual).to(beTruthy());
// Passes if actual is only true (not nil or an object conforming to BooleanType true):
expect(actual).to(beTrue());
// Passes if actual is nil, false, or an object with a boolean value of false:
expect(actual).to(beFalsy());
// Passes if actual is only false (not nil or an object conforming to BooleanType false):
expect(actual).to(beFalse());
// Passes if actual is nil:
expect(actual).to(beNil());
```