AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 79556360
Accepted
Bill
Bill
Asked: 2025-04-05 07:16:13 +0800 CST2025-04-05 07:16:13 +0800 CST 2025-04-05 07:16:13 +0800 CST

O equipamento Pytest está alterando a instância retornada por outro equipamento

  • 772

Estou muito confuso e um pouco preocupado ao descobrir o seguinte comportamento, onde tenho dois testes e dois acessórios.

import pytest


@pytest.fixture
def new_object():
    return list()


@pytest.fixture
def a_string(new_object):
    # Change this instance of the object
    new_object.append(1)
    return "a string"


def test_1(new_object):
    assert len(new_object) == 0


def test_2(a_string, new_object):
    assert len(new_object) == 0

O primeiro teste passa, mas o segundo falha.

    def test_2(a_string, new_object):
>       assert len(new_object) == 0
E       assert 1 == 0
E        +  where 1 = len([1])

tests/test_pytest_list.py:21: AssertionError
================================================ short test summary info =================================================
FAILED tests/test_pytest_list.py::test_2 - assert 1 == 0
============================================== 1 failed, 1 passed in 0.36s ===============================================

Eu esperava que os equipamentos passassem novas instâncias de um objeto (a menos que especificado de outra forma), não o mesmo objeto que algum outro equipamento modificou.

De acordo com a documentação sobre o escopo dos acessórios, está escrito:

o padrão é invocar uma vez por função de teste

Outro equipamento não se qualifica como uma função?

ATUALIZAR

Com base nos comentários, agora entendo o problema, embora eu ainda ache que é um comportamento perigoso para uma ferramenta de teste de unidade.

Aqui está outro uso inválido de fixtures que uma pessoa ingênua como eu pode não perceber que é errado:

@pytest.fixture
def new_object():
    """I want to test instances of this class"""
    return list()


@pytest.fixture
def case_1(new_object):
    new_object.append(1)
    return new_object


@pytest.fixture
def case_2(new_object):
    new_object.append(2)
    return new_object


def test_cases(case_1, case_2):
    assert sum(case_1) + sum(case_2) == 3  # fails: assert (3 + 3) == 3
python
  • 2 2 respostas
  • 59 Views

2 respostas

  • Voted
  1. Best Answer
    Wolric
    2025-04-05T08:18:50+08:002025-04-05T08:18:50+08:00

    O acessório new_objecté invocado para cada teste, conforme você declarou claramente na documentação.

    O problema está no seu segundo equipamento e no uso da combinação de ambos no seu segundo teste.

    Como o pytest permite que você use fixtures mais de uma vez por teste sem afetar uns aos outros, usando retornos em cache .

    Isso significa que, quando o equipamento a_wordusa o equipamento new_objectpela segunda vez, new_objectele é encontrado no seu segundo teste e usa o valor de retorno armazenado em cache da a_wordchamada do equipamento em vez de fornecer outra lista vazia.

    • 3
  2. Bill
    2025-04-05T23:45:32+08:002025-04-05T23:45:32+08:00

    O erro que cometi foi considerar um fixture como um método de fábrica que sempre constrói uma nova instância. Uma maneira melhor de pensar nisso talvez seja um dicionário com um valor padrão que cria apenas uma instância para cada teste e, se chamado mais de uma vez, retorna a mesma instância. O objetivo é evitar recalcular o fixture mais de uma vez (como explicado na resposta de @Wolric).

    Então, para o que quero fazer, uma solução simples é criar uma função de fábrica real fora do Pytest:

    import pytest
    
    def make_new_object():
        """I want to test instances of this class"""
        return list()
    
    
    @pytest.fixture
    def case_1():
        new_object = make_new_object()
        new_object.append(1)
        return new_object
    
    
    @pytest.fixture
    def case_2():
        new_object = make_new_object()
        new_object.append(2)
        return new_object
    
    
    def test_both_cases(case_1, case_2):
        assert sum(case_1) + sum(case_2) == 3
    

    Alternativamente, você pode retornar o método de fábrica como um acessório:

    import pytest
    
    @pytest.fixture
    def make_new_object():
        """Returns a factory method to make new instances of this class"""
        def list_factory():
            return list()
        return list_factory
    
    
    @pytest.fixture
    def case_1(make_new_object):
        new_object = make_new_object()
        new_object.append(1)
        return new_object
    
    
    @pytest.fixture
    def case_2(make_new_object):
        new_object = make_new_object()
        new_object.append(2)
        return new_object
    
    
    def test_both_cases(case_1, case_2):
        assert sum(case_1) + sum(case_2) == 3
    
    • 0

relate perguntas

  • Como divido o loop for em 3 quadros de dados individuais?

  • Como verificar se todas as colunas flutuantes em um Pandas DataFrame são aproximadamente iguais ou próximas

  • Como funciona o "load_dataset", já que não está detectando arquivos de exemplo?

  • Por que a comparação de string pandas.eval() retorna False

  • Python tkinter/ ttkboostrap dateentry não funciona quando no estado somente leitura

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve