GithubHelp home page GithubHelp logo

moocher's Introduction

Moocher Cocoapod Version Swift Version SPM Compatible Cocoapod Platform iOS Deployment Target License

A set of "rspec-like" test matchers that "mooch" off of XCTest.

Adding Moocher to your project

CocoaPods

CocoaPods is the recommended way to add Moocher to your project.

  1. Add Moocher to your Podfile pod 'Moocher'.
  2. Install the pod(s) by running pod install.
  3. Add Moocher to your files with import Moocher.

Swift Package Manager

Swift Package Manager can be used to add Moocher the to your project:

  1. Add .package(url: "https://github.com/rbaumbach/Moocher", from: "0.4.4")
  2. Follow intructions to add the Moocher package to your project.

Note: Since Moocher requires the library XCTest, when you add Moocher to your project, be sure that it's added to your unit testing target.

Clone from Github

  1. Clone repository from github and copy files directly, or add it as a git submodule.
  2. Add all files from Sources/Moocher directory to your project.

Usage

Moocher matchers are inspired by RSpec:

expect(AnswerToUltimateQuestion.value).to.equal(42)

Equivalence and Identity

  • equal

This matcher works for types that conform to Equatable, but also works for types that conform to FloatingPoint as well.

expect(99).to.equal(99)
expect(99).toNot.equal(100)

expect(9.9).to.equal(9.9, within: 0.1)
expect(9.9).toNot.equal(10.9, within: 0.1)

Types

  • beInstanceOf
class Dog { }

let chihuahua = Dog()
let pancho = chihuahua
let miniPinscher = Dog()

expect(chihuahua).to.beInstanceOf(pancho)
expect(chihuahua).toNot.beInstanceOf(miniPinscher)
  • beKindOf
class Dog { }
struct Fish { }

let dog = Dog()

expect(dog).to.beKindOf(Dog.self)
expect(dog).toNot.beKindOf(Fish.self)
  • conformTo
protocol Wolf { }
class Dog: Wolf { }

protocol Goat { }

let dog = Dog()

expect(dog).to.conformTo(Wolf.self)
expect(dog).toNot.conformTo(Goat.self)

Comparisons

  • beLessThan
expect(9).to.beLessThan(10)
expect(9).toNot.beLessThan(8)
  • beLessThanOrEqualTo
expect(9).to.beLessThanOrEqualTo(9)
expect(11).toNot.beLessThanOrEqualTo(10)
  • beGreaterThan
expect(9).to.beGreaterThan(8)
expect(7).toNot.beGreaterThan(8)
  • beGreaterThanOrEqualTo
expect(9).to.beGreaterThanOrEqualTo(8)
expect(7).toNot.beGreaterThanOrEqualTo(8)

Truthiness

  • beTruthy
expect(true).to.beTruthy()
expect(false).toNot.beTruthy()
  • beFalsy
expect(false).to.beFalsy()
expect(true).toNot.beFalsy()
  • beNil
var number: Int?

expect(number).to.beNil()

number = 99

expect(number).toNot.beNil()

Error Throwing

  • throwError

The throwError matcher can be used in 4 different ways:

  • throwError(block:)
expect({ try functionThatThrowsAnError() })
    .to.throwError()
expect({ try functionThatDoesNotThrowAnError() })
    .toNot.throwError()
  • throwError(block:errorHandler:)
expect({ try functionThatThrowsAnError() })
    .to.throwError { (error: ErrorType) in
        // Do something with error
    }
  • throwError(block:specificError:)
expect({ try functionThatThrowsABurritoError() })
    .to.throwError(specificError: BurritoError.beansMissing))
expect({ try functionThatThrowsABurritoError() })
    .toNot.throwError(specificError: TacoError.salsaMissing))
  • throwError(block:errorType:)
expect({ try functionThatThrowsABurritoError() })
    .to.throwError(errorType: BurritoError.self))
expect({ try functionThatThrowsABurritoError() })
    .toNot.throwError(errorType: TacoError.self))

Collection

  • beEmpty

This matcher works for types that conform to Collection.

let emptyArray: [Int] = []

expect(emptyArray).to.beEmpty()
expect([1, 2, 3]).toNot.beEmpty()

This matcher also works for Strings as well.

expect("").to.beEmpty()
expect("Taco").toNot.beEmpty()
  • startWith
expect(["a", "b", "c"]).to.startWith("a")
expect([2, 4, 8]).toNot.startWith(1)

This matcher also works for Strings as well.

expect("Double Dragon").to.startWith("D")
expect("Bimmy and Jimmy Lee").toNot.startWith("Billy")
  • endWith
expect(["a", "b", "c"]).to.endWith("c")
expect([2, 4, 8]).toNot.endWith(7)

This matcher also works for Strings as well.

expect("Double Dragon").to.endWith("n")
expect("Bimmy and Jimmy Lee").toNot.endWith("Smith")
  • haveSizeOf
expect(["taco", "burrito"]).to.haveSizeOf(2)
expect([2, 4, 8]).toNot.haveSizeOf(7)
  • contain
expect(["uno", "dos", "tres"]).to.contain("tres")
expect("Billy Goat").toNot.contain("$")

This matcher also works for finding a substring within a String.

expect("Corey and Trevor").to.contain("and")
expect("Richard LaFleur").toNot.contain("Smart")

Compound matchers

Some of the matchers allow for compounding assertions:

expect([1, 2, 3]).to.contain(1).and.startWith(1).and.endWith(3)
expect([1, 2, 3]]).toNot.haveSizeOf(4).and.contain(7)

The following matchers can be used compoundly:

  • startWith
  • endWith
  • contain
  • haveSizeOf
  • haveMinValueOf
  • haveMaxValueOf

Moocher Polling

This repo also contains an additional library for polling values when writing integration tests that have to "wait" for assertions.

This can be added to your project:

CocoaPods

  1. Add MoocherPolling to your Podfile pod 'Moocher/Polling'.
  2. Install the pod(s) by running pod install.
  3. Add MoocherPolling to your files with import MoocherPolling.

Swift Package Manager

  1. Add MoocherPolling to your target: Build Phases -> Link Binary With Libraries.
  2. Add MoocherPolling to your files with import MoocherPolling.

HangOn

HangOn is a function that allows block input that will wait for an assertion given a specific timeframe.

var number = 100

hangOn(for: .seconds(10)) { complete in
    DispatchQueue.global(qos: .background).async { [weak self] in
        sleep(3)
        
        number = 99
        
        DispatchQueue.main.async {
            expect(number).to.equal(99)
            
            complete()
        }
    }
}

toSomeday and toNever

Values can be constantly polled using familiar expect syntax using toSomeday and toNever.

var dogArray = ["Chihuhahua", "Miniature Pinscher", "Border Collie"]

DispatchQueue.global(qos: .background).async {
    sleep(3)

    dogArray.append("German Shepard")
}

expect(dogArray).toSomeday.contain("German Shepard")
var dogArray = ["Chihuhahua", "Miniature Pinscher", "Border Collie"]

DispatchQueue.global(qos: .background).async {
    sleep(3)

    dogArray.append("German Shepard")
}

expect(dogArray).toNever.contain("Poodle")

The expect clause will block tests from running until either a timeout has been hit, or the assertion you expect is true. The default timeout is 5 seconds. This can be set by providing a timeout value.

The interval in which the polling is done on the value being asserted has a default interval of 100 milliseconds. This can be set by providing a pollingInterval value.

expect(dogArray, timeout: .seconds(10), pollingInterval: .miliseconds(500)).toSomeday.contain("German Shepard")

The following matchers can be used for toSomeday and toNever:

  • beNil
  • beTruthy
  • beFalsy
  • equal
  • contain

moocher's People

Contributors

rbaumbach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

moocher's Issues

Enhance Dictionary matcher

  • Enhance contains() method for Dictionary types where you can check key/value pairs.
  • Add beEmpty() for Dictionary types.

Add a test wrapper

If you are writing specs using a closure based framework (such as Quick), you will easily run into the following compiler error when using new fancy Swift concurrency stuffs:

Mutation of captured var 'variable' in concurrently-executing code

An easy way to bypass this is to create a wrapper that you can create with a let, and then mutate a property internally that can be accessed:

final class TestWrapper<T> {
    var value: T?
    
    init(value: T? = nil) {
        self.value = value
    }
}

To be safe as well, create an @Atomic property wrapper that can be used on the value.

Add Utils subspec

Create a new subspec to place utils that can be used that aren't necessarily tied to Moocher. Also, lets make the default subspec include all specs to follow CocoaPod podspec best practices.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.