<p><strong>Meta Description:</strong> Aprenda testes de contrato: Pact, contratos entre microservices, consumer-driven testing e como evitar breaking changes.</p>

<hr>
<h2>O Que São Testes de Contrato?</h2>

<p>Testes de contrato verificam que a interface entre serviços (API) está funcionando conforme acordado. Cada serviço define o que espera e o que fornece.</p>

<h3>Problema</h3>

<pre><code>Microservice A (Consumer)
        ↓
    API REST
        ↓
Microservice B (Provider)

<p>Se B muda API sem avisar A → BUG!<br></code></pre></p>

<h3>Solução: Contract Testing</h3>

<pre><code>┌─────────────┐                    ┌─────────────┐
│  Consumer   │    Contract       │  Provider   │
│   Test      │ ←──────────────→ │   Test      │
└─────────────┘                    └─────────────┘
     ↓                                  ↓
[Pact Broker] ←──────────────────────────
</code></pre>

<hr>
<h2>Pact - Framework de Contract Testing</h2>

<h3>Setup</h3>

<pre><code># Ruby
gem install pact

<p># Python<br>pip install pact-python</p>

<p># Java<br><br>    au.com.dius.pact<br>    jvm-consumer<br>    4.6.4<br><br></code></pre></p>

<h3>Consumer Test (Python)</h3>

<pre><code># test_consumer.py
import pact

<p># Provider URL<br>PACT_MOCK_PROVIDER_URL = "http://localhost:1234"</p>

<p># Define consumer and provider<br>consumer = pact.Consumer('OrderService')<br>provider = pact.Provider('ProductService')</p>

<p># Create pact<br>order_service_pact = consumer.has_pact_with(<br>    provider,<br>    pact_dir='./pacts',<br>    log_dir='./logs'<br>)</p>

<p># Test<br>order_service_pact.given(<br>    'product with id 1 exists'<br>).upon_receiving(<br>    'a request for product details'<br>).with_request(<br>    method='GET',<br>    path='/products/1'<br>).will_respond_with(<br>    status=200,<br>    headers={'Content-Type': 'application/json'},<br>    body={<br>        'id': 1,<br>        'name': pact.Match.something_like('Test Product'),<br>        'price': pact.Match.decimal(99.99),<br>        'in_stock': pact.Match.boolean(True)<br>    }<br>)</p>

<p># Verify<br>with order_service_pact:<br>    result = requests.get(f'{PACT_MOCK_PROVIDER_URL}/products/1')<br>    assert result.status_code == 200<br>    assert result.json()['name'] == 'Test Product'<br></code></pre></p>

<h3>Provider Test (Python)</h3>

<pre><code># test_provider.py
import pact
from pact import Verifier

<p># Verify against provider<br>verifier = Verifier(<br>    provider='ProductService',<br>    provider_base_url='http://localhost:8000'<br>)</p>

<p># Set up Pact file to verify<br>verifier.provider_states(<br>    'http://localhost:8000',<br>    set_up=lambda state: create_test_product() if state == 'product with id 1 exists' else None,<br>    tear_down=lambda state: delete_test_product() if state == 'product with id 1 exists' else None<br>)</p>

<p># Verify contracts<br>result = verifier.verify_pacts(<br>    './pacts/order_service-product_service.json',<br>    verbose=True<br>)</p>

<p>assert result == 0, f"Pact verification failed: {result}"<br></code></pre></p>

<hr>
<h2>Pact Broker</h2>

<pre><code># Publish contract
pact-broker publish ./pacts 
  --consumer-app-version=1.0.0 
  --broker-base-url=https://pact-broker.example.com 
  --broker-token=YOUR_TOKEN

<p># Can I Deploy?<br>pact-broker can-i-deploy <br>  --pacticipant=OrderService <br>  --version=1.0.0 <br>  --to-environment=production<br></code></pre></p>

<hr>
<h2>Conclusão</h2>

<p>Contract testing previne breaking changes. As chaves são:<br><ol><li><strong>Consumer-driven</strong> - Cada cliente define necessidades</li><br><li><strong>Pact broker</strong> - Centraliza contratos</li><br><li><strong>Verificação contínua</strong> - CI valida mudanças</li><br><li><strong>Can I Deploy</strong> - Bloca deploys incompatíveis</li></ol></p>