Skip to content

Commit

Permalink
Merge pull request #4 from thefuntasty/feature/documentation
Browse files Browse the repository at this point in the history
Add documentation
  • Loading branch information
mkj-is authored Oct 21, 2019
2 parents 34d31ee + 88c9d46 commit d8ee3a4
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 10 deletions.
2 changes: 1 addition & 1 deletion FTTestingKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "FTTestingKit"
s.version = "0.2.0"
s.version = "0.3.0"
s.summary = "Mockup and asynchronous testing protocols and extensions."
s.description = <<-DESC
Testing helpers for easier testing mockups and asynchronous testing.
Expand Down
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,92 @@
# FTTestingKit

A description of this package.
![Cocoapods](https://img.shields.io/cocoapods/v/FTTestingKit)
![Cocoapods platforms](https://img.shields.io/cocoapods/p/FTTestingKit)
![Cocoapods](https://img.shields.io/cocoapods/l/FTTestingKit)
![Bitrise](https://img.shields.io/bitrise/f8e8740dfdd3c6a2?token=_ejKL14TVCB_KLWT4-wDxw)

A set of helpers for simple creation of mockups, random values and testing of asynchronous code.

## Installation

When using Swift package manager add this line
to your dependencies or install using Xcode 11 or newer:

```swift
.package(url: "https://github.com/thefuntasty/FTTestingKit.git", from: "0.3.0")
```

When using CocoaPods add following line to your `Podfile`:

```ruby
pod 'FTTestingKit', '~> 0.3'
```

When using `PromiseKit` you can use either `FTTestingKitPromiseKit`
target for testing promises or add subspec to your `Podfile`:

```ruby
pod 'FTTestingKit', '~> 0.3', subspecs: ['PromiseKit']
```

## Features

Main features of this library are generating mockups,
random values, arrays and asynchronous testing.

### Mockups

For simple repeated execution the library offers Ruby-like extension on `Int` type. This is helpful in measurement tests.

```swift
10.times {
doSomething()
}
10.times(doSomething)
```

This extension can create arrays too:

```swift
10.times {
Int.random()
}
10.times(String.random)
```

The framework extends some basic types (`Date`, `String`)
with random generation similar to `Int`.
All these types conform to `Mockup` protocol
which formally describes this functionality.

```swift
Date.random()
String.random()
Int.random(count: 10)
```

### Expectations

The framework extends `XCTestCase` with simple methods to call transactional asynchronous test like this:

```swift
expect(within: 0.5) { reply in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
reply(.success)
}
}
```

Extension for `PromiseKit` builds on this and offers testing promises using so-called belief in promise method:

```swift
believe(for: 0.5, in: someFunctionReturningPromise())
```

## Author

Matěj Kašpar Jirásek, <[email protected]>

## License

FTTestingKit is available under the MIT license. See the [LICENSE file](LICENSE) for more info.
13 changes: 10 additions & 3 deletions Sources/FTTestingKit/Int+Times.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
public extension Int {
func times(execute: () -> Void) {
extension Int {
/// Executes supplied closure n-times.
/// Handy for time measurement tests.
/// - Parameter execute: Closure executed n-times.
public func times(execute: () -> Void) {
for _ in 0..<self {
execute()
}
}

func times<T>(execute: () -> T) -> [T] {
/// Creates array of items by executing supplied
/// closure n-times. Handy for generating
/// arrays of random values.
/// - Parameter execute: Closure returning some item n-times.
public func times<T>(execute: () -> T) -> [T] {
return (0..<self).map { _ in execute() }
}
}
5 changes: 5 additions & 0 deletions Sources/FTTestingKit/Mockup.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/// Protocol unifying the form of randomly generated mockups.
public protocol Mockup {
/// Generates one randomly generated mockup.
static func random() -> Self
/// Generates array of randomly generated mockups.
/// - Parameter count: Number of generated items.
static func random(count: Int) -> [Self]
}

public extension Mockup {
Expand Down
1 change: 1 addition & 0 deletions Sources/FTTestingKit/Result+Void.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
public extension Result where Success == Void {
/// Convenience case for success results with void values.
static var success: Result<Void, Error> {
return .success(())
}
Expand Down
3 changes: 3 additions & 0 deletions Sources/FTTestingKit/String+Mockup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ extension String: Mockup {
return random(length: 15, characters: mockupCharacters)
}

/// Generates random string of required length from supplied characters.
/// - Parameter length: Length of the generated string in characters.
/// - Parameter characters: Array of characters used to generate the random string.
public static func random(
length: Int,
characters: [Character]
Expand Down
6 changes: 6 additions & 0 deletions Sources/FTTestingKit/XCTest+Expect.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import XCTest

public extension XCTestCase {
/// Executes new asynchronous test using expectation and encapsulates the operation
/// into transaction inside a closure.
/// - Parameter seconds: Seconds until the expectations will time-out.
/// - Parameter reply: Closure for encapsulating asynchronous tests into transactions,
/// the parameter of the clousre is callback for returning the result
/// of the asynchronous operation.
func expect(
within seconds: TimeInterval,
reply: @escaping (@escaping (Result<Void, Error>) -> Void) -> Void
Expand Down
10 changes: 10 additions & 0 deletions Sources/FTTestingKitPromiseKit/XCTest+Believe.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import FTTestingKit
#endif

public extension XCTestCase {
/// Executes new asynchronous test using expectation and encapsulates the operation
/// into a closure returning promise.
/// - Parameter timeInterval: Number of seconds until the test will time-out.
/// - Parameter promise: Operation encapsulated inside of promise which will be
/// tested for time-out and successful result.
func believe<T>(for timeInterval: TimeInterval, in promise: @escaping @autoclosure () throws -> Promise<T>) {
expect(within: timeInterval) { reply in
firstly { try promise() }.asVoid().recover { error in
Expand All @@ -15,6 +20,11 @@ public extension XCTestCase {
}
}

/// Executes new asynchronous test using expectation and encapsulates the operation
/// into a closure returning guarantee.
/// - Parameter timeInterval: Number of seconds until the test will time-out.
/// - Parameter promise: Operation encapsulated inside of guarantee which will be
/// tested for time-out and successful result.
func believe<T>(for timeInterval: TimeInterval, in guarantee: @escaping @autoclosure () -> Guarantee<T>) {
expect(within: timeInterval) { reply in
guarantee().asVoid().done {
Expand Down
4 changes: 2 additions & 2 deletions Tests/FTTestingKitPromiseKitTests/BelieveTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import FTTestingKitPromiseKit

final class BelieveTests: XCTestCase {
func testInstantPromise() {
believe(for: 0.1, in: Promise())
believe(for: 0.5, in: Promise())
}

func testDelayedPromise() {
believe(for: 0.1, in: after(seconds: 0.05))
believe(for: 0.5, in: after(seconds: 0.05))
}

static var allTests = [
Expand Down
6 changes: 3 additions & 3 deletions Tests/FTTestingKitTests/ExpectationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import FTTestingKit

final class ExpectationTests: XCTestCase {
func testInstantExpectation() {
expect(within: 0.1) { reply in
expect(within: 0.5) { reply in
reply(.success)
}
}

func testAsyncExpectation() {
expect(within: 0.1) { reply in
expect(within: 0.5) { reply in
DispatchQueue.main.async {
reply(.success)
}
}
}

func testDelayedExpectation() {
expect(within: 0.1) { reply in
expect(within: 0.5) { reply in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
reply(.success)
}
Expand Down

0 comments on commit d8ee3a4

Please sign in to comment.