I'm trying to introduce contract testing to my team, and Pact seems to be the only reliable tool out there.
The complication is that the documentation suggests to use it with microservices and as a part of CI pipeline. But we can't make such a big change to our infrastructure, and instead I try to modify Pact usage to fit our needs.
I want to use Pact to test communications between JavaScript (Karma + Mocha) frontend and Rails (Rspec) backend via REST API. Everything is working fine, except I can't make it work reliably on CI (Circle CI). We don't have a CI pipeline, as it is suggested in Pact docs, instead we want to simply run Consumer and Provider tests in one container one after another. And the artifact will be just stored in the temporary folder in the container and removed afterwards.
The question: is there any established and reliable way of running Pact tests on CI in one container without a pipeline? Or Pact will not be the best tool for this job?
I wrote a ruby script to accomplish that, but it often crashes with a timeout:
def test_pact
# wait for pact server to start, identify it by pid in the STDOUT
server_init_message = "WEBrick::HTTPServer#start: pid="
server_error_message = "(Errno::EADDRINUSE)"
read_stream, write_stream = IO.pipe
proc = ChildProcess.build("bundle", "exec", "rake", "pact:server")
proc.io.stdout = proc.io.stderr = write_stream
proc.leader = true # makes sure to kill all child forks of this process when it dies
begin
proc.start
output_line = read_stream.gets
until output_line.include?(server_init_message)
puts "Waiting for Pact server to boot: #{Time.now}"
output_line = read_stream.gets
puts "Server output: #{output_line}"
raise "Server boot error" if output_line.include?(server_error_message)
end
puts "Pact Server is booted"
# Run JS tests:
Dir.chdir("js") do
run_or_exit("./build-support/circle.js", 'contract-karma.conf.js')
end
proc.stop
# Run Ruby tests:
run_or_exit("bundle exec rake pact:verify")
rescue ChildProcess::TimeoutError, RuntimeError
proc.stop
end
end
And a Rake task:
require 'pact/tasks'
task :default => 'pact:verify'
# rake pact:server
namespace :pact do
desc 'Run Pact Mock Server'
task server: :environment do
puts 'starting Pact mock server'
system 'pact-mock-service --host localhost --port 1234 --pact_dir spec/contracts --consumer "Some Service" --provider "Some Service Provider" --pact_specification_version 2'
end
end