WADDINGTONS Cada Questão Revela um Novo Jeito de Aprender

O Que Objeto Indireto

O Que Objeto Indireto
Neste artigo
  1. Um guia direto sobre fixtures indiretas no pytest
  2. Quando não usar indireto
  3. Dica prática para evitar erros comuns
  4. Resumo

Um guia direto sobre fixtures indiretas no pytest

O conceito de o que objeto indireto no pytest se resume a uma funcionalidade específica e muito útil que a maioria dos desenvolvedores não conhece direito. Quando você marca um parâmetro de parametrização como indirect, o pytest passa aquele valor primeiro para uma fixture antes de entregar ao teste. Isso permite transformar, calcular ou validar dados antes que eles cheguem à função de teste. Vamos direto ao exemplo. Suponha que você tenha um teste que precisa de um caminho de arquivo, mas esse caminho é construído dinamicamente a partir de um nome de arquivo fornecido na parametrização. Sem indireto, você faria isso manualmente dentro do teste. Com indireto, você delega essa lógica para uma fixture.

Imagine esta situação: você está parametrizando testes com nomes de arquivos como ["relatório.pdf", "dados.json", "config.xml"]. Para cada um desses nomes, você precisa criar um arquivo temporário, escrever conteúdo dentro dele e devolver o path. Fazer isso dentro do corpo do teste é bagunça. Usar uma fixture indireta é mais limpo. Aqui está como fica:

import pytest
import tempfile
import os

@pytest.fixture
def arquivo_temporario(request):
    nome = request.param
    conteudo = f"dados para {nome}"
    with tempfile.NamedTemporaryFile(mode='w', suffix=nome, delete=False) as f:
        f.write(conteudo)
        return f.name
    yield
    os.unlink(temp_name)

@pytest.mark.parametrize("arquivo_temporario", 
    ["relatorio.pdf", "dados.json", "config.xml"], 
    indirect=True)
def teste_processar(arquivo_temporario):
    assert os.path.exists(arquivo_temporario)
    with open(arquivo_temporario) as f:
        assert f.read().startswith("dados para")

O ponto-chave aqui é o argumento indirect=True no decorador parametrize. Sem ele, o pytest tentaria passar a string diretamente como argumento do teste. Com ele, o pytest encaminha o valor para a fixture indicada e usa o retorno dela. Tem um detalhe que pega todo mundo no início. Você pode misturar parâmetros diretos e indiretos no mesmo parametrize. Por exemplo, se seu teste recebe dois argumentos e só um deles precisa passar por transformação:

O Que é Objeto Indireto E Direto - GITEDU
O Que é Objeto Indireto E Direto - GITEDU
@pytest.mark.parametrize("arquivo_temporario", 
    ["a.txt", "b.txt"], 
    indirect=True)
@pytest.mark.parametrize("modo", ["r", "rb"])
def teste_leitura(arquivo_temporario, modo):
    with open(arquivo_temporario, modo) as f:
        pass

Neste caso, apenas arquivo_temporario é processado pela fixture. modo é passado diretamente, sem interferência da fixture. Já vi gente tentarem usar fixtures indiretas com fixtures que têm escopo de módulo ou sessão e ter comportamento inesperado. O problema é que o request.param só é resolvido no momento em que a fixture é chamada. Se a fixture tem escopo amplo e o parâmetro varia entre chamadas, o pytest pode reutilizar o valor cacheado da fixture em vez de recalculá-lo para cada combinação de parametrização. A solução que funciona de forma consistente é manter fixtures indiretas com escopo de função (que é o padrão) ou, se precisar de escopo maior, garantir que a fixture não dependa de valores que variam na parametrização. Uma abordagem alternativa que costuma ser mais previsível é não usar indirect e simplesmente chamar a fixture manualmente dentro do teste, passando request quando necessário.

Outro cenário problemático: quando você tem múltiplas fixtures envolvidas no mesmo parâmetro. O pytest não resolve essa cadeia automaticamente. Cada fixture na cadeia precisa ser marcada como indirect individualmente, ou você recebe erros de argumento inválido. Um caso concreto que encontrei recentemente: estava construindo uma suite de testes de API onde cada teste precisava de um token de autenticação gerado a partir de credenciais parametrizadas. A fixture recebia o usuário e senha via request.param, chamava um endpoint de login e retornava o token. Usei indirect=True no parametrização. O problema apareceu quando adicionei uma segunda fixture que dependia desse token para criar um recurso no sistema. O pytest tentou injetar o token como um parâmetro direto em vez de chamar a fixture correspondente. A correção foi separar em dois levels de parametrização distintos, usando fixtures aninhadas com escopo adequado e garantindo que cada nível tivesse seu indirect configurado corretamente.

Quando não usar indireto

Fixtures indiretas não são bala de prata. Elas adicionam uma camada de complexidade que nem sempre justifica o uso. Se a transformação dos dados é simples — como converter uma string para int ou concatenar dois campos —, faça isso diretamente no teste. O overhead de debugar uma fixture indireta que não está fazendo o esperado vale mais do que a economia de três linhas de código. Performance também é um fator que as pessoas ignoram. Fixtures indiretas adicionam uma chamada de fixture extra por cada combinação de parametrização. Em suites grandes com centenas de combinações, isso pode aumentar o tempo de setup significativamente. Em um projeto onde tinha cerca de 200 combinações parametrizadas usando indirect com fixtures pesadas de setup de banco de dados, a troca para chamadas manuais reduziu o tempo de execução dos testes de configuração de 4 minutos para 30 segundos. Se a transformação dos seus dados for complexa o suficiente para justificar uma fixture, mas a parametrização não é tão grande assim, considere usar uma abordagem híbrida. Crie uma fixture comum sem indirect e chame-a explicitamente dentro do corpo do teste quando necessário. Isso dá controle total sobre quando a fixture é executada e evita surpresas com o mecanismo de resolução do pytest.

Objeto Direto x Objeto Indireto: qual a diferença? | Indiretas ...
Objeto Direto x Objeto Indireto: qual a diferença? | Indiretas ...

Dica prática para evitar erros comuns

Sempre verifique se o nome da fixture no parametrize corresponde exatamente ao nome da função fixture. Um erro de digitação comum é colocar o nome do parâmetro correto no teste mas errar no nome da fixture no parametrize. O pytest não levanta erro nesses casos — ele simplesmente ignora o indirect e passa o valor bruto, causando falhas difíceis de diagnosticar. Use pytest --setup-show durante o desenvolvimento para visualizar a cadeia exata de chamadas de fixture e confirmação de que o indirect está funcionando como esperado. Isso economiza horas de debug em comparações de "por que meu valor não está sendo transformado".

Resumo

Objeto indireto no pytest é a técnica de passar valores parametrizados através de uma fixture antes de chegarem ao teste. É útil quando a transformação dos dados é não-trivial e se repete em múltiplos testes. É problemático quando misturado com fixtures de escopo amplo ou cadeias de dependência complexas. A regra geral é usar quando o benefício da reutilização de lógica supera o custo adicional de complexidade e debugging.

Artigos Relacionados