All Projects → DiUS → pact-consumer-swift

DiUS / pact-consumer-swift

Licence: MIT license
A Swift / ObjeciveC DSL for creating pacts.

Programming Languages

swift
15916 projects
shell
77523 projects
objective c
16641 projects - #2 most used programming language
ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to pact-consumer-swift

pact-example
Example project to demonstrate Contract Testing via Pact.
Stars: ✭ 58 (-34.83%)
Mutual labels:  pact, contract-testing
ContractTestingBoilerplate
Contract Testing Boilerplate for the microservices developed using Spring Boot and Kafka in a maven multi-module project.
Stars: ✭ 36 (-59.55%)
Mutual labels:  pact, contract-testing
sample-testing-microservices
sample applications with implementation of unit, component, contract and integrarion tests using pact, gatling, spring boot test and hoverfly
Stars: ✭ 22 (-75.28%)
Mutual labels:  pact, contract-testing
README
Developer Relations @ Pact - Your map to the Pact landscape for all-comers (maintainers, contributors, users, newbies)
Stars: ✭ 35 (-60.67%)
Mutual labels:  pact, contract-testing
pact-mock service
Provides a mock service for use with Pact
Stars: ✭ 66 (-25.84%)
Mutual labels:  pact
testing-microservices-introduction
Learn some of the high level microservices testing cases with hands on examples.
Stars: ✭ 27 (-69.66%)
Mutual labels:  pact
pact-js-core
Core binaries for pact-js, a Contract Testing Framework. NOTE: If you are looking to do Pact contract testing in node, you almost certainly want pact-js, not pact-node.
Stars: ✭ 140 (+57.3%)
Mutual labels:  pact
Karate
Test Automation Made Simple
Stars: ✭ 5,497 (+6076.4%)
Mutual labels:  contract-testing
terraform-provider-pact
Terraform provider for Pact Broker (and Pactflow)
Stars: ✭ 21 (-76.4%)
Mutual labels:  pact
pmpact
A command line tool to convert Pact files to Postman collections.
Stars: ✭ 15 (-83.15%)
Mutual labels:  pact
go-microservices-and-krakend-api-gateway
This is a shopping basket workshop that shows how to use KrakenD API Gateway.
Stars: ✭ 44 (-50.56%)
Mutual labels:  pact
pact-workshop-dotnet-core-v1
A workshop for Pact using .NET Core
Stars: ✭ 66 (-25.84%)
Mutual labels:  pact
MQBench Quantize
QAT(quantize aware training) for classification with MQBench
Stars: ✭ 29 (-67.42%)
Mutual labels:  pact
portman
Port OpenAPI Specs to Postman Collections, inject test suite and run via Newman 👨🏽‍🚀
Stars: ✭ 530 (+495.51%)
Mutual labels:  contract-testing
rust-wildbow-scraper
Automatically scrapes wildbow's web serials and compiles them into ebooks
Stars: ✭ 64 (-28.09%)
Mutual labels:  pact
Javascript Testing Best Practices
📗🌐 🚢 Comprehensive and exhaustive JavaScript & Node.js testing best practices (August 2021)
Stars: ✭ 13,976 (+15603.37%)
Mutual labels:  contract-testing
jest-pact
A Pact adaptor for to allow you to easily run tests with Jest
Stars: ✭ 58 (-34.83%)
Mutual labels:  pact
karate
Test Automation Made Simple
Stars: ✭ 6,384 (+7073.03%)
Mutual labels:  contract-testing
spring-projects
Some spring sample projects
Stars: ✭ 24 (-73.03%)
Mutual labels:  pact
nirvana-teste-de-contrato
Example of how to implement nirvana of contract testing with Pact following all the practices described in https://docs.pact.io/pact_nirvana
Stars: ✭ 71 (-20.22%)
Mutual labels:  pact

Pact Consumer Swift

Build Codecov Carthage compatible Swift Package Manager Swift Badge w/ CocoaPod Version Badge w/ Supported Platforms License: MIT Twitter


A new version featuring Pact Specification v3, a simplified installation and better management of the mock server processes is in active development and can be found at PactSwift. We are currently looking for people to try it out and provide feedback.

This library provides a Swift / Objective C DSL for creating Consumer Pacts. It provides support for Consumer Driven Contract Testing between dependent systems where the integration is based on HTTP (or message queues for some of the implementations).

But why? To test communication boundaries between your app and services. You can view a presentation on how Pact can work in a mobile context here: Yow! Connected 2016 Andrew Spinks - Increasing The Confidence In Your Service Integrations.

Implements Pact Specification v2, including flexible matching.

This DSL relies on the Ruby pact-ruby-standalone (brew tap) to provide the mock service for the tests.

Installation

Note: see Upgrading for notes on upgrading from 0.2 to 0.3

Install Pact Mock Service

Homebrew

brew tap pact-foundation/pact-ruby-standalone
brew install pact-ruby-standalone

This will install the following tools:

pact
pact-broker
pact-message
pact-mock-service
pact-provider-verifier
pact-publish
pact-stub-service

Manually

Alternatively you can download and install the pact-ruby-standalone archives for your platform and install as per installation instructions written in Pact Ruby Standalone release notes.

Xcode Setup

In Xcode, edit your scheme and add pre- and post-actions to Test to start and stop pact-mock-service. Make sure you select your target in Provide build settings from the drop down menu.

# Pre-actions
PATH=/path/to/your/standalone/pact/bin:$PATH
pact-mock-service start --pact-specification-version 2.0.0 --log "${SRCROOT}/tmp/pact.log" --pact-dir "${SRCROOT}/tmp/pacts" -p 1234

# Post-actions
PATH=/path/to/your/standalone/pact/bin:$PATH
pact-mock-service stop

Note: your generated Pact files will be dropped into "${SRCROOT}/tmp/pacts" folder.

Xcode Scheme Test Pre-actions

Add the PactConsumerSwift library to your project

Using Carthage

  • See the PactSwiftExample Swift, Carthage Example - Build Status for an example project using pact-consumer-swift with Carthage for an iOS target.
  • See the PactMacOSExample Build for an example project using pact-consumer-swift through Carthage for a macOS target.

Using CocoaPods

  • See the PactObjectiveCExample Build Status for an example project using pact-consumer-swift with CocoaPods for an iOS target.

Using Swift Package Manager

  • See the PactSwiftPMExample Build for an example project using pact-consumer-swift library through Swift Package Manager for an executable that runs in terminal.

Writing Pact Tests

Testing with Swift

Write a Unit test similar to the following (NB: this example is using the Quick test framework)

import PactConsumerSwift

...
  beforeEach {
    animalMockService = MockService(provider: "Animal Service", consumer: "Animal Consumer Swift")
    animalServiceClient = AnimalServiceClient(baseUrl: animalMockService!.baseUrl)
  }

  it("gets an alligator") {
    animalMockService!.given("an alligator exists")
                      .uponReceiving("a request for an alligator")
                      .withRequest(method:.GET, path: "/alligator")
                      .willRespondWith(status:200,
                                       headers: ["Content-Type": "application/json"],
                                       body: ["name": "Mary"])

    //Run the tests
    animalMockService!.run { (testComplete) -> Void in
      animalServiceClient!.getAlligator { (alligator) in
        expect(alligator.name).to(equal("Mary"))
        testComplete()
      }
    }
  }

An optional timeout (seconds) parameter can be included on the run function. This defaults to 30 seconds.

...
    animalMockService!.run(timeout: 60) { (testComplete) -> Void in
      animalServiceClient!.getAlligator { (alligator) in
        expect(alligator.name).to(equal("Mary"))
        testComplete()
      }
    }

Testing with Objective-C

Write a Unit test similar to the following

@import PactConsumerSwift;
...
- (void)setUp {
  [super setUp];
  self.animalMockService = [[MockService alloc] initWithProvider:@"Animal Provider"
                                                        consumer:@"Animal Service Client Objective-C"];
  self.animalServiceClient = [[OCAnimalServiceClient alloc] initWithBaseUrl:self.animalMockService.baseUrl];
}

- (void)testGetAlligator {
  typedef void (^CompleteBlock)();

  [[[[self.animalMockService given:@"an alligator exists"]
                             uponReceiving:@"oc a request for an alligator"]
                             withRequestHTTPMethod:PactHTTPMethodGET
                                              path:@"/alligator"
                                             query:nil headers:nil body:nil]
                             willRespondWithHTTPStatus:200
                                               headers:@{@"Content-Type": @"application/json"}
                                                  body: @"{ \"name\": \"Mary\"}" ];

  [self.animalMockService run:^(CompleteBlock testComplete) {
      Animal *animal = [self.animalServiceClient getAlligator];
      XCTAssertEqualObjects(animal.name, @"Mary");
      testComplete();
  }];
}

An optional timeout (seconds) parameter can be included on the run function. This defaults to 30 seconds.

...
  [self.animalMockService run:^(CompleteBlock testComplete) {
      Animal *animal = [self.animalServiceClient getAlligator];
      XCTAssertEqualObjects(animal.name, @"Mary");
      testComplete();
  } timeout:60];
}

Testing with XCTest

Write a Unit Test similar to the following:

import PactConsumerSwift
...
  var animalMockService: MockService?
  var animalServiceClient: AnimalServiceClient?

  override func setUp() {
    super.setUp()

    animalMockService = MockService(provider: "Animal Provider", consumer: "Animal Service Client")
    animalServiceClient = AnimalServiceClient(baseUrl: animalMockService!.baseUrl)
  }

  func testItGetsAlligator() {
    // Prepare the expecated behaviour using pact's MockService
    animalMockService!
      .given("an alligator exists")
      .uponReceiving("a request for alligator")
      .withRequest(method: .GET, path: "/alligator")
      .willRespondWith(status: 200,
                       headers: ["Content-Type": "application/json"],
                       body: [ "name": "Mary" ])

    // Run the test
    animalMockService!.run(timeout: 60) { (testComplete) -> Void in
      self.animalServiceClient!.getAlligator { (response) -> in
        XCTAssertEqual(response.name, "Mary")
        testComplete()
      }
    }
  }
  ...

An optional timeout (seconds) parameter can be included on the run function. Defaults to 30 seconds.

...
    // Run the test
    animalMockService!.run(timeout: 60) { (testComplete) -> Void in
      self.animalServiceClient!.getAlligator { (response) -> in
        XCTAssertEqual(response.name, "Mary")
        testComplete()
      }
    }

For an example on how to test over https see PactSSLSpec.swift.

Matching

In addition to verbatim value matching, you have 3 useful matching functions in the Matcher class that can increase expressiveness and reduce brittle test cases.

  • Matcher.term(matcher, generate) - tells Pact that the value should match using a given regular expression, using generate in mock responses. generate must be a string.
  • Matcher.somethingLike(content) - tells Pact that the value itself is not important, as long as the element type (valid JSON number, string, object etc.) itself matches.
  • Matcher.eachLike(content, min) - tells Pact that the value should be an array type, consisting of elements like those passed in. min must be >= 1. content may be a valid JSON value: e.g. strings, numbers and objects.

NOTE: One caveat to note, is that you will need to use valid Ruby regular expressions and double escape backslashes.

See the PactSpecs.swift, PactObjectiveCTests.m for examples on how to expect error responses, how to use query params, and Matchers.

For more on request / response matching, see [Matching][getting_started/matching].

Using in your CI

Xcode's pre-actions and post-actions do not honour non-zero script exits and therefore would not fail your build if publishing to a Pact Broker would fail. If you would like to upload your Pact files to a Pact Broker as part of your CI, we would suggest that you create a separate step in your CI workflow with that responsibility.

See pact-ruby-standalone page for installation instructions and how to use pact-broker client.

Verifying your client against the service you are integrating with

If your setup is correct and your tests run against the pack mock server, then you should see a log file here: $YOUR_PROJECT/tmp/pact.log And the generated pacts here: $YOUR_PROJECT/tmp/pacts/...

Publish your generated pact file(s) to your Pact Broker or a Hosted Pact Broker so your API provider can always retrieve them from one location, even when pacts change. Or even just by simply sending the pact file to your API provider devs so they can used them in their tests of their API responses. See Verifying pacts for more information. For an end-to-end example with a ruby back end service, have a look at the KatKit example.

Also, check out this article on using a dockerized Node.js service that uses provider states.

More reading

  • The Pact website Pact
  • The pact mock server that the Swift library uses under the hood Pact mock service
  • A pact broker for managing the generated pact files (so you don't have to manually copy them around!) Pact broker

Contributing

Please read CONTRIBUTING.md

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].