Merge pull request #43 from jeffh/beTrue-beFalse-matchers
Refactored BeLogical. Added beTrue() and beFalse() matchers. Closes #24
This commit is contained in:
Коммит
b5cb2a792d
|
@ -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
|
||||
|
|
12
README.md
12
README.md
|
@ -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());
|
||||
```
|
||||
|
|
Загрузка…
Ссылка в новой задаче