Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

Add consumer side of WIT+Auth contract tests. #2393

Merged
merged 31 commits into from
Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
43cdc1a
contract-tests: Add contract tests.
pmacik Nov 9, 2018
d774c30
contract-tests: Implement consumer of fabric8auth service.
pmacik Jan 11, 2019
ef0cebe
contract-tests: Add CICO job script.
pmacik Jan 17, 2019
ece3cde
contract-tests: Update according to #2939 suggestions
pmacik Jan 21, 2019
07d2cbb
contract-tests: Update package names and workaround pact-go#108 issue.
pmacik Jan 22, 2019
189ead0
contract-tests: Move publishing to a separate make target.
pmacik Jan 23, 2019
2ad63c6
contract-tests: Update cico job to publish pact to broker.
pmacik Jan 24, 2019
05969c4
contract-tests: Rearange test files/packages.
pmacik Jan 28, 2019
bdcdf36
Update .make/test.mk
kwk Jan 29, 2019
2452c80
Update .make/test.mk
kwk Jan 29, 2019
8a5de57
Update .make/test.mk
kwk Jan 29, 2019
51c5800
Update test/contracts/.gitignore
kwk Jan 29, 2019
5f134b3
Update .make/test.mk
kwk Jan 29, 2019
7dfed09
Update .make/test.mk
kwk Jan 29, 2019
3928198
Update test/contracts/.gitignore
kwk Jan 29, 2019
9db26af
contract-tests: Move auth model closer.
pmacik Feb 1, 2019
46de846
Use GOLINT_DIR instead of hard-coded path
pmacik Feb 1, 2019
37b0d23
Make it run :)
pmacik Feb 1, 2019
660ebeb
contract-tests: Set PactDir and LogDir properly to be in tmp directory.
pmacik Feb 4, 2019
62dba45
contract-tests: Ensure Pact CLI is installed in the CICO script.
pmacik Feb 6, 2019
47c043f
contract-tests: Optionally disable cico_setup function.
pmacik Feb 13, 2019
908f3d9
Merge branch 'master' into contract-tests-poc
pmacik Feb 14, 2019
5aabcc3
contract-tests: Add pact-go in Gopkg.toml.
pmacik Feb 14, 2019
4047d95
contract-tests: Remove hashicorp/logutils 'hack' to suppress DEBUG ou…
pmacik Feb 14, 2019
08070e7
contract-tests: Add logrus dependency into Gopkg.toml.
pmacik Feb 19, 2019
cd4c62e
contract-tests: Workaround 'set -e' for pact-mock-service check.
pmacik Feb 19, 2019
4f70d36
contract-tests: Make it work on CICO job.
pmacik Feb 19, 2019
0b13e6b
contract-tests: Fix cico setup.
pmacik Feb 19, 2019
8853962
contract-tests: Fix docker container name in cico script.
pmacik Feb 20, 2019
33ced80
contract_tests: Load PACT_* env variables from Jenkins.
pmacik Feb 20, 2019
f8189b4
Merge branch 'master' into contract-tests-poc
pmacik Feb 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .make/test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,38 @@ test-integration-benchmark: prebuild-check migrate-database $(SOURCES)
$(eval TEST_PACKAGES:=$(shell go list ./... | grep -v $(ALL_PKGS_EXCLUDE_PATTERN)))
F8_DEVELOPER_MODE_ENABLED=1 F8_RESOURCE_DATABASE=1 F8_RESOURCE_UNIT_TEST=0 F8_LOG_LEVEL=$(F8_LOG_LEVEL) go test -run=^$$ -bench=. -cpu 1,2,4 -test.benchmem $(GO_TEST_VERBOSITY_FLAG) $(TEST_PACKAGES) | grep -E "Bench|allocs"

.PHONY: test-contracts-consumer-no-coverage
## Runs the consumer side of contract tests WITHOUT producing coverage files for each package.
test-contracts-consumer-no-coverage:
$(call log-info,"Running test: $@")
$(eval TEST_PACKAGES:=$(shell go list ./... | grep -e 'contracts/consumer'))
$(eval PACT_DIR=$(PWD)/test/contracts/pacts)
pmacik marked this conversation as resolved.
Show resolved Hide resolved
$(eval PACT_VERSION="latest")
go test $(GO_TEST_VERBOSITY_FLAG) -count=1 $(TEST_PACKAGES)

.PHONY: publish-contract-testing-pacts-to-broker
## Publishes generated Pact file (the contracts) to the Pact broker.
## The following env variables needs to be set in environment:
## - Pact broker for storing pact files
## PACT_BROKER_URL
## PACT_BROKER_USERNAME
## PACT_BROKER_PASSWORD
publish-contract-testing-pacts-to-broker:
$(call log-info,"Publishing pact files to Broker")
$(eval PACT_DIR=$(PWD)/test/contracts/pacts)
pmacik marked this conversation as resolved.
Show resolved Hide resolved
$(eval PACT_FILES:=$(shell find $(PACT_DIR) -name '*.json'))
$(eval PACT_VERSION?=1.0.0)
$(eval PACT_TAGS?=latest)
go run ./test/contracts/publisher/main.go "$(PACT_FILES)" "$(PACT_VERSION)" "$(PACT_TAGS)"

.PHONY: clean-contract-tests
pmacik marked this conversation as resolved.
Show resolved Hide resolved
## Cleans generated pacts and logs from contract tests
clean-contract-tests:
$(call log-info,"Cleaning generated pacts and logs from contract tests")
$(eval PACT_DIR=$(PWD)/test/contracts/pacts)
pmacik marked this conversation as resolved.
Show resolved Hide resolved
$(eval LOGS_TO_BE_CLEANED:=$(shell find test/contracts -name '*logs'))
pmacik marked this conversation as resolved.
Show resolved Hide resolved
rm -rvf $(PACT_DIR) $(LOGS_TO_BE_CLEANED)

.PHONY: test-remote
## Runs the remote tests and produces coverage files for each package.
test-remote: prebuild-check clean-coverage-remote $(COV_PATH_REMOTE)
Expand Down
34 changes: 34 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions cico_run_contract_tests_consumer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

. cico_setup.sh

cico_setup;

set -e

# Run the contract tests
make test-contracts-consumer-no-coverage

# Publish the generated Pact files to Pact broker.
make publish-contract-testing-pacts-to-broker
4 changes: 4 additions & 0 deletions test/contracts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pacts
pmacik marked this conversation as resolved.
Show resolved Hide resolved
output
**/*/log
pmacik marked this conversation as resolved.
Show resolved Hide resolved
**/*/logs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**/*/logs

37 changes: 37 additions & 0 deletions test/contracts/consumer/fabric8auth/api_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package fabric8auth_test

import (
"log"
"testing"

"github.com/fabric8-services/fabric8-auth/test/contracts/model"
"github.com/fabric8-services/fabric8-wit/test/contracts"
"github.com/fabric8-services/fabric8-wit/test/contracts/consumer"
"github.com/pact-foundation/pact-go/dsl"
)

// AuthAPIStatus defines contract of /api/status endpoint
func AuthAPIStatus(t *testing.T, pact *dsl.Pact) {

log.Printf("Invoking AuthAPIStatus now\n")

// Set up our expected interactions.
pact.
AddInteraction().
Given("Auth service is up and running.").
UponReceiving("A request to get status").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/status"),
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.status+json")},
Body: dsl.Match(model.APIStatusMessage{}),
})

// Verify
err := pact.Verify(consumer_test.SimpleGetInteraction(pact, "/api/status"))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}
36 changes: 36 additions & 0 deletions test/contracts/consumer/fabric8auth/api_token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package fabric8auth_test

import (
"log"
"testing"

"github.com/fabric8-services/fabric8-auth/test/contracts/model"
"github.com/fabric8-services/fabric8-wit/test/contracts"
"github.com/fabric8-services/fabric8-wit/test/contracts/consumer"
"github.com/pact-foundation/pact-go/dsl"
)

// AuthAPITokenKeys defines contract of /api/status endpoint
func AuthAPITokenKeys(t *testing.T, pact *dsl.Pact) {

log.Printf("Invoking AuthAPITokenKeys now\n")

// Set up our expected interactions.
pact.
AddInteraction().
Given("Auth service is up and running.").
UponReceiving("A request to get public keys").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/token/keys"),
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.publickeys+json")},
Body: dsl.Match(model.TokenKeys{}),
})

// Verify
err := pact.Verify(consumer_test.SimpleGetInteraction(pact, "/api/token/keys"))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}
167 changes: 167 additions & 0 deletions test/contracts/consumer/fabric8auth/api_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package fabric8auth_test

import (
"fmt"
"log"
"testing"

"github.com/fabric8-services/fabric8-auth/test/contracts/model"
"github.com/fabric8-services/fabric8-wit/test/contracts"
consumer "github.com/fabric8-services/fabric8-wit/test/contracts/consumer"
"github.com/pact-foundation/pact-go/dsl"
)

// AuthAPIUserByName defines contract of /api/users?filter[username]=<user_name> endpoint
func AuthAPIUserByName(t *testing.T, pact *dsl.Pact, userName string) {

log.Println("Invoking AuthAPIUserByName test interaction now")

// Set up our expected interactions.
pact.
AddInteraction().
Given("User with a given username exists.").
UponReceiving("A request to get user's information by username").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/users"),
Query: dsl.MapMatcher{
"filter[username]": dsl.Term(
userName,
model.UserNameRegex,
),
},
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")},
Body: dsl.Match(model.Users{}),
})

// Verify
err := pact.Verify(consumer.SimpleGetInteraction(pact, fmt.Sprintf("/api/users?filter[username]=%s", userName)))
contracts_test.CheckErrorAndCleanPact(t, pact, err)
}

// AuthAPIUserByID defines contract of /api/users/<user_id> endpoint
func AuthAPIUserByID(t *testing.T, pact *dsl.Pact, userID string) {

log.Printf("Invoking AuthAPIUserByID test interaction now\n")

// Set up our expected interactions.
pact.
AddInteraction().
Given("User with a given ID exists.").
UponReceiving("A request to get user's information by ID").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.Term(
fmt.Sprintf("/api/users/%s", userID),
fmt.Sprintf("/api/users/%s", model.UserIDRegex),
),
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json")},
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")},
Body: dsl.Match(model.User{}),
})

// Verify
err := pact.Verify(consumer.SimpleGetInteraction(pact, fmt.Sprintf("/api/users/%s", userID)))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}

// AuthAPIUserByToken defines contract of /api/user endpoint with valid auth token
// passed as 'Authorization: Bearer ...' header
func AuthAPIUserByToken(t *testing.T, pact *dsl.Pact, userToken string) {

log.Printf("Invoking AuthAPIUserByToken test interaction now\n")

// Pass in test case
// Set up our expected interactions.
pact.
AddInteraction().
Given("A user exists with the given valid token.").
UponReceiving("A request to get user's information with valid auth token ").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/user"),
Headers: dsl.MapMatcher{
"Content-Type": dsl.String("application/json"),
"Authorization": dsl.Term(
fmt.Sprintf("Bearer %s", userToken),
fmt.Sprintf("^Bearer %s$", model.JWSRegex),
),
},
}).
WillRespondWith(dsl.Response{
Status: 200,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")},
Body: dsl.Match(model.User{}),
})

// Verify
err := pact.Verify(consumer.SimpleGetInteractionWithToken(pact, "/api/user", userToken))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}

// AuthAPIUserInvalidToken defines contract of /api/user endpoint with invalid auth token
func AuthAPIUserInvalidToken(t *testing.T, pact *dsl.Pact, invalidToken string) {

log.Printf("Invoking AuthAPIUserInvalidToken test interaction now\n")

// Set up our expected interactions.
pact.
AddInteraction().
Given("No user exists with the given token valid.").
UponReceiving("A request to get user's information with invalid auth token ").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/user"),
Headers: dsl.MapMatcher{
"Content-Type": dsl.String("application/json"),
"Authorization": dsl.Term(
fmt.Sprintf("Bearer %s", invalidToken),
fmt.Sprintf("^Bearer %s$", model.JWSRegex),
),
},
}).
WillRespondWith(dsl.Response{
Status: 401,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")},
Body: dsl.Match(model.InvalidTokenMessage{}),
})

// Verify
err := pact.Verify(consumer.SimpleGetInteractionWithToken(pact, "/api/user", invalidToken))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}

// AuthAPIUserNoToken defines contract of /api/user endpoint with missing auth token
func AuthAPIUserNoToken(t *testing.T, pact *dsl.Pact) {

log.Printf("Invoking AuthAPIUserNoToken test interaction now\n")

// Set up our expected interactions.
pact.
AddInteraction().
Given("Any user exists but no auth token was provided.").
UponReceiving("A request to get user's information with no auth token ").
WithRequest(dsl.Request{
Method: "GET",
Path: dsl.String("/api/user"),
Headers: dsl.MapMatcher{
"Content-Type": dsl.String("application/json"),
},
}).
WillRespondWith(dsl.Response{
Status: 401,
Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/vnd.api+json")},
Body: dsl.Match(model.MissingTokenMessage{}),
})

// Verify
err := pact.Verify(consumer.SimpleGetInteraction(pact, "/api/user"))
contracts_test.CheckErrorAndCleanPact(t, pact, err) //workaround for https://github.com/pact-foundation/pact-go/issues/108
}
Loading