pytest · conftest · Luhn

Gerador de Cartão para Testes em pytest

Fixture pytest com cartão sintético válido pelo algoritmo Luhn (mod-10). Session fixture pra economizar API calls, conftest.py compartilhado, integração pytest-django + pytest-mock. SDK fakeforge-br. Ambiente de desenvolvimento apenas.

Ferramenta para desenvolvedores. Os cartão de crédito gerados são sintéticos e não pertencem a nenhuma pessoa real. Uso restrito a testes de software, seed de banco de dados de desenvolvimento e fixtures de QA. Usar em cadastro real ou apresentar como documento verdadeiro configura falsidade ideológica (art. 299 CP).

TL;DR

pip install fakeforge-br pytest pytest-mock

# conftest.py
import pytest
from fakeforge import FakeForge

@pytest.fixture(scope="session")
def cartoes(ff):
    return ff.credit_card(50)

conftest.py compartilhado

# tests/conftest.py
import pytest
from fakeforge import FakeForge

@pytest.fixture(scope="session")
def ff():
    return FakeForge()

@pytest.fixture(scope="session")
def cartoes(ff):
    """50 cartões sintéticos pré-carregados."""
    return ff.credit_card(50)

@pytest.fixture(scope="session")
def cartoes_visa(ff):
    """20 cartões filtrados Visa."""
    return [c for c in ff.credit_card(100) if c["brand"] == "visa"][:20]

@pytest.fixture(scope="function")
def cartao(ff):
    """1 cartão novo por teste."""
    return ff.credit_card(1)[0]

Teste de checkout com parametrize

# tests/test_checkout.py
import pytest
from myapp.checkout import CheckoutService

class TestCheckoutLuhn:
    @pytest.mark.parametrize("indice", range(20))
    def test_aceita_cartao_com_luhn_valido(self, cartoes, indice):
        cartao = cartoes[indice]
        service = CheckoutService()
        resultado = service.validar(cartao["number"])
        assert resultado.valido, f"Rejeitou cartão válido: {cartao['number']}"

    def test_rejeita_luhn_invalido(self):
        service = CheckoutService()
        assert not service.validar("1234 5678 9012 3456").valido

    def test_rejeita_formato_incorreto(self):
        service = CheckoutService()
        assert not service.validar("").valido
        assert not service.validar("abc").valido

Mock de gateway Stripe (pytest-mock)

# tests/test_payment_service.py
class TestPaymentService:
    @pytest.fixture(autouse=True)
    def mock_stripe(self, mocker):
        mock = mocker.patch("stripe.PaymentIntent.create")
        mock.return_value = type("PI", (), {"id": "pi_mock", "status": "succeeded"})()
        return mock

    def test_paga_com_cartao_sintetico(self, cartao, mock_stripe):
        from myapp.payment import PaymentService
        result = PaymentService.pay(
            card_number=cartao["number"],
            amount_cents=5000,
        )
        assert result.status == "succeeded"
        mock_stripe.assert_called_once()

Django checkout model (pytest-django)

# tests/test_pedido_model.py
import pytest
from myapp.models import Pedido

@pytest.mark.django_db
class TestPedidoModel:
    def test_salva_pedido_com_cartao_sintetico(self, cartao):
        pedido = Pedido.objects.create(
            cliente_id=1,
            valor_total=15000,
            cartao_numero=cartao["number"],
            cartao_bandeira=cartao["brand"],
            status="pago",
        )
        assert pedido.pk is not None

    def test_bulk_seed_500_pedidos(self, cartoes):
        pedidos = [
            Pedido(
                cliente_id=i,
                valor_total=10000 + (i * 100),
                cartao_numero=cartoes[i % len(cartoes)]["number"],
                cartao_bandeira=cartoes[i % len(cartoes)]["brand"],
                status="pago",
            )
            for i in range(500)
        ]
        Pedido.objects.bulk_create(pedidos)
        assert Pedido.objects.count() == 500