Testes de Contrato para Microsserviços com Pact PHP

O desenvolvimento de sistemas sempre modificou-se rapidamente ao decorrer do tempo. Novos paradigmas de programação foram criados, novos tipos de linguagem, metodologias e processos. A arquitetura dos softwares também não poderia ficar fora, começando com uma arquitetura monolítica, passando para uma arquitetura orientada a serviços (SOA), até a arquitetura com maior destaque no momento, os microsserviços.

Testes de contrato com Pact PHP

O Pact, é um framework de teste que ajuda você a escrever contratos, e garante que esses contratos estejam atendidos. O Pact tem implementações para várias linguagens, entre elas, Java, .NET, Javascript, Go, Python, Swift e PHP.

$ composer require phpunit/phpunit — dev$ composer require mattersight/phppact — dev
{
"require-dev": {
"phpunit/phpunit": "^6.2",
"mattersight/phppact": "^3.0”
}
}
$ php ../vendor/phpunit/phpunit/phpunit -c phpunit.example.one.xml
PHPUnit 6.5.8 by Sebastian Bergmann and contributors.Starting the mock service with command '/home/fsilva/Documents/dev/php-pact/vendor/mattersight/phppact/src/PhpPact/Standalone/Installer/../../../../pact/bin/pact-mock-service' 'service' '--consumer=ExampleOne' '--provider=ExampleAPI' '--pact-dir=/tmp' '--pact-file-write-mode=overwrite' '--host=localhost' '--port=7200'.
[2018-04-18 22:33:17] INFO WEBrick 1.3.1
[2018-04-18 22:33:17] INFO ruby 2.2.2 (2015-04-13) [x86_64-linux]
[2018-04-18 22:33:17] INFO WEBrick::HTTPServer#start: pid=11881 port=7200
. 1 / 1 (100%)[2018-04-18 22:33:17] INFO going to shutdown ...
[2018-04-18 22:33:18] INFO WEBrick::HTTPServer#start done.
I, [2018-04-18T22:33:17.859136 #11881] INFO -- : Registered expected interaction GET /2/categories
D, [2018-04-18T22:33:17.860161 #11881] DEBUG -- : {
"description": "General Meetup Categories",
"providerState": "A GET request to return JSON using Meetups category api under version 2",
"request": {
"method": "GET",
"path": "/2/categories",
"headers": {
"Content-Type": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"results": {
"json_class": "Pact::ArrayLike",
"contents": {
"name": {
"json_class": "Pact::Term",
"data": {
"generate": "Games",
"matcher": {"json_class":"Regexp","o":0,"s":"[gbBG]"}
}
},
"sort_name": "Games",
"id": 11,
"shortname": "Games"
},
"min": 1
}
}
}
}
I, [2018-04-18T22:33:17.870039 #11881] INFO -- : Received request GET /2/categories
D, [2018-04-18T22:33:17.870314 #11881] DEBUG -- : {
"path": "/2/categories",
"query": "",
"method": "get",
"headers": {
"Content-Type": "application/json",
"Host": "localhost:7200",
"User-Agent": "GuzzleHttp/6.3.2 curl/7.55.1 PHP/7.1.16",
"Version": "HTTP/1.1"
}
}
I, [2018-04-18T22:33:17.870853 #11881] INFO -- : Found matching response for GET /2/categories
D, [2018-04-18T22:33:17.871244 #11881] DEBUG -- : {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"results": {
"json_class": "Pact::ArrayLike",
"contents": {
"name": {
"json_class": "Pact::Term",
"data": {
"generate": "Games",
"matcher": {
"json_class": "Regexp",
"o": 0,
"s": "[gbBG]"
}
}
},
"sort_name": "Games",
"id": 11,
"shortname": "Games"
},
"min": 1
}
}
}
I, [2018-04-18T22:33:17.884214 #11881] INFO -- : Verifying - interactions matched
I, [2018-04-18T22:33:17.936178 #11881] INFO -- : Verifying - interactions matched
I, [2018-04-18T22:33:17.941931 #11881] INFO -- : Writing pact for ExampleAPI to /tmp/exampleone-exampleapi.json
Process exited with code 0.
PACT_BROKER_URI environment variable was not set. Skipping PACT file upload.
Time: 2.76 seconds, Memory: 6.00MBOK (1 test, 3 assertions)
{
"consumer": {
"name": "ExampleOne"
},
"provider": {
"name": "ExampleAPI"
},
"interactions": [
{
"description": "General Meetup Categories",
"providerState": "A GET request to return JSON using Meetups category api under version 2",
"request": {
"method": "GET",
"path": "/2/categories",
"headers": {
"Content-Type": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"body": {
"results": [
{
"name": "Games",
"sort_name": "Games",
"id": 11,
"shortname": "Games"
}
]
},
"matchingRules": {
"$.body.results": {
"min": 1
},
"$.body.results[*].*": {
"match": "type"
},
"$.body.results[*].name": {
"match": "regex",
"regex": "[gbBG]"
}
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}

Conclusão — Testes de contratos para microsserviços em PHP

A evolução dos sistemas para microsserviços resultou com que novos problemas entrassem em foco, fazendo com que métodos alternativos de testes ganhassem mais destaque além dos testes tradicionais. Apesar de muitas empresas terem experiências ruins na migração para este tipo de arquitetura, existem vantagens bem relevantes em relação a aderir ao uso deste tipo de tecnologia, como builds e entregas mais rápidas e modularidade das API’s. Se quiser saber mais sobre microsserviços, no artigo Microsserviços: Distribuindo serviços críticos ao negócio falo sobre um case que a equipe que eu trabalho na KingHost desenvolveu, abordando vantagens, desvantagens, dificuldades e como migramos nosso sistema monolítico.

Application Security Analyst na Compasso UOL, mestre em Ciência da Computação e pós-graduado em Segurança Cibernética pela UFRGS.

Application Security Analyst na Compasso UOL, mestre em Ciência da Computação e pós-graduado em Segurança Cibernética pela UFRGS.