Estoy usando Pytest con Django y llegué a este extraño comportamiento. Tengo dos accesorios de usuario, uno de los cuales es un superconjunto del otro. Todo funciona como se esperaba hasta que uso ambos accesorios en el mismo caso de prueba.
Accesorios:
@pytest.fixture def user_without_password(): return User.objects.create_user(username=fake.name(), email=fake.email()) @pytest.fixture def user_with_password(user_without_password): user = user_without_password user.set_password('topsecret') user.save() return userPruebas
@pytest.mark.django_db() def test_without_pass(user_without_password): assert not user_without_password.has_usable_password() @pytest.mark.django_db() def test_with_pass(user_with_password): assert user_with_password.has_usable_password() # THIS FAILS!! @pytest.mark.django_db() def test_both(user_with_password, user_without_password): assert not user_without_password.has_usable_password() assert user_with_password.has_usable_password() La última prueba no funciona ya que aparentemente user_with_password y user_without_password terminan siendo el mismo objeto. ¿Hay alguna manera de garantizar que sean objetos nuevos cada vez? Este comportamiento se siente contrario a la intuición.
Los accesorios de pytest están diseñados para ser eficientes, es decir, si un accesorio se solicita varias veces, solo se crea una vez. Eso significa que siempre puede solicitar un dispositivo de otro dispositivo y asegurarse de que está utilizando el mismo objeto que la prueba.
Además, si lee su dispositivo user_with_password de esta manera:
Entonces tiene sentido que el dispositivo que devuelve al usuario que creó sin contraseña continúe devolviendo a ese usuario, pero ahora se le ha agregado una contraseña.
Si desea evitar esto, cree un accesorio que cree nuevos objetos en lugar de un solo objeto, algo como:
@pytest.fixture def user_without_password_factory(): def create_user_without_password(): return User.objects.create_user(username=fake.name(), email=fake.email()) return create_user_without_password @pytest.fixture def user_with_password_factory(): def create_user_with_password(): user = User.objects.create_user(username=fake.name(), email=fake.email()) user.set_password('topsecret') user.save() return user return create_user_with_password @pytest.mark.django_db() def test_without_pass(user_without_password_factory): assert not user_without_password_factory().has_usable_password() @pytest.mark.django_db() def test_with_pass(user_with_password_factory): assert user_with_password_factory().has_usable_password() # Succeeds!! @pytest.mark.django_db() def test_both(user_with_password_factory, user_without_password_factory): assert not user_without_password_factory().has_usable_password() assert user_with_password_factory().has_usable_password()