From 1fe4ef768dbad77a833a4ecc70a07207d4bda641 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 15:34:52 -0400
Subject: [PATCH 01/23] Update plugin.py

---
 pytest_django/plugin.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index 08d961a6..fc439819 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -599,7 +599,8 @@ def _dj_autoclear_mailbox() -> None:
 
     from django.core import mail
 
-    del mail.outbox[:]
+    if hasattr(main, "outbox":
+        mail.outbox.clear()
 
 
 @pytest.fixture()

From acd9d6182b5db49e0715e76c1abc1982aa981ad0 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 15:37:33 -0400
Subject: [PATCH 02/23] Update plugin.py

---
 pytest_django/plugin.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index fc439819..2309c9ed 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -599,7 +599,7 @@ def _dj_autoclear_mailbox() -> None:
 
     from django.core import mail
 
-    if hasattr(main, "outbox":
+    if hasattr(main, "outbox"):
         mail.outbox.clear()
 
 

From 502380faa59d98c6137f74b14abe05170423d832 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 15:41:33 -0400
Subject: [PATCH 03/23] Update test_environment.py

---
 tests/test_environment.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index a3549732..2823d813 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -18,6 +18,23 @@
 # to do it.
 
 
+@pytest.mark.django_project(
+    project_root="django_project_root",
+    extra_settings="""
+    EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
+    """,
+)
+def test_manage_test_runner(django_pytester: DjangoPytester) -> None:
+    django_pytester.create_test_module(
+        """
+        def test_bad_mail():
+            pass
+        """
+    )
+    result = django_pytester.runpytest_subprocess("-s")
+    assert "1 passed" in "\n".join(result.outlines)
+
+
 @pytest.mark.parametrize("subject", ["subject1", "subject2"])
 def test_autoclear_mailbox(subject: str) -> None:
     assert len(mail.outbox) == 0

From c8427b437f48efdf9ff3c3090a10e52dd2f4cc46 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 15:42:37 -0400
Subject: [PATCH 04/23] i want to see it fail

---
 pytest_django/plugin.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index 2309c9ed..eece6a51 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -599,8 +599,9 @@ def _dj_autoclear_mailbox() -> None:
 
     from django.core import mail
 
-    if hasattr(main, "outbox"):
-        mail.outbox.clear()
+    del mail.outbox[:]
+    # if hasattr(main, "outbox"):
+    #     mail.outbox.clear()
 
 
 @pytest.fixture()

From 9e786dba0541d97cc8a285e90d453f9e496d95af Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 15:48:41 -0400
Subject: [PATCH 05/23] Update test_environment.py

---
 tests/test_environment.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index 2823d813..26876ab5 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -32,7 +32,7 @@ def test_bad_mail():
         """
     )
     result = django_pytester.runpytest_subprocess("-s")
-    assert "1 passed" in "\n".join(result.outlines)
+    assert "1 passed" in "\n".join([*result.outlines, *result.errlines])
 
 
 @pytest.mark.parametrize("subject", ["subject1", "subject2"])

From b9dee6aec323ffe6d78b5da9ace65a0e1608690e Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Mon, 31 Mar 2025 17:47:51 -0400
Subject: [PATCH 06/23] This is a much bigger issue.

---
 pytest_django/plugin.py   |  7 ++++---
 tests/test_environment.py | 26 +++++++++++++++++++++++---
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index eece6a51..fe315fe5 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -599,9 +599,10 @@ def _dj_autoclear_mailbox() -> None:
 
     from django.core import mail
 
-    del mail.outbox[:]
-    # if hasattr(main, "outbox"):
-    #     mail.outbox.clear()
+    # import ipdb; print('\a'); ipdb.sset_trace()
+    # del mail.outbox[:]
+    if hasattr(mail, "outbox"):
+        mail.outbox.clear()
 
 
 @pytest.fixture()
diff --git a/tests/test_environment.py b/tests/test_environment.py
index 26876ab5..8e375c65 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -19,19 +19,39 @@
 
 
 @pytest.mark.django_project(
-    project_root="django_project_root",
     extra_settings="""
     EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
+    import unittest.mock
+    from types import SimpleNamespace
+
+    def setup_test_environment(*a, **k):
+        if hasattr(_TestState, "saved_data"):
+            # Executing this function twice would overwrite the saved values.
+            raise RuntimeError(
+                "setup_test_environment() was already called and can't be called "
+                "again without first calling teardown_test_environment()."
+            )
+
+        saved_data = SimpleNamespace()
+        _TestState.saved_data = saved_data
+        saved_data.allowed_hosts = []
+        saved_data.debug = False
+        saved_data.email_backend = None
+        saved_data.template_render = None
+
+    unittest.mock.patch("django.test.utils.setup_test_environment", setup_test_environment).start()
+    from django.test.utils import _TestState
     """,
 )
-def test_manage_test_runner(django_pytester: DjangoPytester) -> None:
+def test_mail_auto_fixture(django_pytester: DjangoPytester) -> None:
     django_pytester.create_test_module(
         """
         def test_bad_mail():
             pass
         """
     )
-    result = django_pytester.runpytest_subprocess("-s")
+    result = django_pytester.runpytest_subprocess("-s", "-vv")
+    print("\n".join([*result.outlines, *result.errlines]))
     assert "1 passed" in "\n".join([*result.outlines, *result.errlines])
 
 

From 2b5b1977927177ec8de7744d4e380c5ed76b4ea3 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 10:59:21 +0200
Subject: [PATCH 07/23] Update test_environment.py

---
 tests/test_environment.py | 22 ++--------------------
 1 file changed, 2 insertions(+), 20 deletions(-)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index 8e375c65..687bbe69 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -21,26 +21,8 @@
 @pytest.mark.django_project(
     extra_settings="""
     EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
-    import unittest.mock
-    from types import SimpleNamespace
-
-    def setup_test_environment(*a, **k):
-        if hasattr(_TestState, "saved_data"):
-            # Executing this function twice would overwrite the saved values.
-            raise RuntimeError(
-                "setup_test_environment() was already called and can't be called "
-                "again without first calling teardown_test_environment()."
-            )
-
-        saved_data = SimpleNamespace()
-        _TestState.saved_data = saved_data
-        saved_data.allowed_hosts = []
-        saved_data.debug = False
-        saved_data.email_backend = None
-        saved_data.template_render = None
 
-    unittest.mock.patch("django.test.utils.setup_test_environment", setup_test_environment).start()
-    from django.test.utils import _TestState
+    unittest.mock.patch("pytest_django.lazy_django.django_settings_is_configured", lambda: False).start()
     """,
 )
 def test_mail_auto_fixture(django_pytester: DjangoPytester) -> None:
@@ -50,7 +32,7 @@ def test_bad_mail():
             pass
         """
     )
-    result = django_pytester.runpytest_subprocess("-s", "-vv")
+    result = django_pytester.runpytest_subprocess("-s")
     print("\n".join([*result.outlines, *result.errlines]))
     assert "1 passed" in "\n".join([*result.outlines, *result.errlines])
 

From 60a07b2a12596bd8777cb915ed2bfc64abe8b48a Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 11:00:07 +0200
Subject: [PATCH 08/23] Update test_environment.py

---
 tests/test_environment.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index 687bbe69..98cb79d6 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -22,6 +22,7 @@
     extra_settings="""
     EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
 
+    import unittest.mock
     unittest.mock.patch("pytest_django.lazy_django.django_settings_is_configured", lambda: False).start()
     """,
 )

From e831c77373cbda0b28e8e548180dbcfc83d0de5c Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 11:49:43 +0200
Subject: [PATCH 09/23] getting closer..

---
 pytest_django/plugin.py   |  5 ++---
 tests/test_environment.py | 11 +++++++----
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index fe315fe5..b479fefb 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -599,8 +599,6 @@ def _dj_autoclear_mailbox() -> None:
 
     from django.core import mail
 
-    # import ipdb; print('\a'); ipdb.sset_trace()
-    # del mail.outbox[:]
     if hasattr(mail, "outbox"):
         mail.outbox.clear()
 
@@ -616,7 +614,8 @@ def mailoutbox(
 
     from django.core import mail
 
-    return mail.outbox  # type: ignore[no-any-return]
+    if hasattr(mail, "outbox"):
+        return mail.outbox  # type: ignore[no-any-return]
 
 
 @pytest.fixture()
diff --git a/tests/test_environment.py b/tests/test_environment.py
index 98cb79d6..a568c60f 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -19,21 +19,24 @@
 
 
 @pytest.mark.django_project(
+    create_manage_py=True,
     extra_settings="""
     EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
 
     import unittest.mock
-    unittest.mock.patch("pytest_django.lazy_django.django_settings_is_configured", lambda: False).start()
+    unittest.mock.patch("django.test.utils.setup_test_environment", lambda *a, **k: None).start()
+    unittest.mock.patch("django.test.utils.teardown_test_environment", lambda *a, **k: None).start()
     """,
 )
 def test_mail_auto_fixture(django_pytester: DjangoPytester) -> None:
     django_pytester.create_test_module(
         """
-        def test_bad_mail():
-            pass
+        def test_bad_mail(settings, mailoutbox):
+            assert mailoutbox is None
+            assert settings.EMAIL_BACKEND == "django.core.mail.backends.dummy.EmailBackend"
         """
     )
-    result = django_pytester.runpytest_subprocess("-s")
+    result = django_pytester.runpytest_subprocess("-s", '-vv')
     print("\n".join([*result.outlines, *result.errlines]))
     assert "1 passed" in "\n".join([*result.outlines, *result.errlines])
 

From e5631311edb1a0b62643df954296de56c30261ca Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 12:01:50 +0200
Subject: [PATCH 10/23] got to the root issue, its a custom
 django_test_environment

---
 tests/test_environment.py | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index a568c60f..9188acbe 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -22,13 +22,19 @@
     create_manage_py=True,
     extra_settings="""
     EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
-
-    import unittest.mock
-    unittest.mock.patch("django.test.utils.setup_test_environment", lambda *a, **k: None).start()
-    unittest.mock.patch("django.test.utils.teardown_test_environment", lambda *a, **k: None).start()
     """,
 )
 def test_mail_auto_fixture(django_pytester: DjangoPytester) -> None:
+    django_pytester.create_test_module(
+        """
+        import pytest
+
+        @pytest.fixture(autouse=True, scope="session")
+        def django_test_environment(request):
+            yield
+        """, filename="conftest.py"
+    )
+
     django_pytester.create_test_module(
         """
         def test_bad_mail(settings, mailoutbox):

From 43da9ac17508208a28620c0b1b6758c029ce2b20 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 12:17:45 +0200
Subject: [PATCH 11/23] Moved test

---
 tests/test_environment.py | 29 -----------------------------
 tests/test_fixtures.py    | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/tests/test_environment.py b/tests/test_environment.py
index 9188acbe..a3549732 100644
--- a/tests/test_environment.py
+++ b/tests/test_environment.py
@@ -18,35 +18,6 @@
 # to do it.
 
 
-@pytest.mark.django_project(
-    create_manage_py=True,
-    extra_settings="""
-    EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
-    """,
-)
-def test_mail_auto_fixture(django_pytester: DjangoPytester) -> None:
-    django_pytester.create_test_module(
-        """
-        import pytest
-
-        @pytest.fixture(autouse=True, scope="session")
-        def django_test_environment(request):
-            yield
-        """, filename="conftest.py"
-    )
-
-    django_pytester.create_test_module(
-        """
-        def test_bad_mail(settings, mailoutbox):
-            assert mailoutbox is None
-            assert settings.EMAIL_BACKEND == "django.core.mail.backends.dummy.EmailBackend"
-        """
-    )
-    result = django_pytester.runpytest_subprocess("-s", '-vv')
-    print("\n".join([*result.outlines, *result.errlines]))
-    assert "1 passed" in "\n".join([*result.outlines, *result.errlines])
-
-
 @pytest.mark.parametrize("subject", ["subject1", "subject2"])
 def test_autoclear_mailbox(subject: str) -> None:
     assert len(mail.outbox) == 0
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 39c6666f..4c98b899 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -825,3 +825,37 @@ def mocked_make_msgid(*args, **kwargs):
     result = django_pytester.runpytest_subprocess("--tb=short", "-vv", "-s")
     result.stdout.fnmatch_lines(["*test_mailbox_inner*", "django_mail_dnsname_mark", "PASSED*"])
     assert result.ret == 0
+
+
+@pytest.mark.django_project(
+    create_manage_py=True,
+    extra_settings="""
+    EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend"
+    """,
+)
+def test_mail_auto_fixture_misconfigured(django_pytester: DjangoPytester) -> None:
+    """
+    django_test_environment fixture can be overridden by user, and that would break mailoutbox fixture.
+
+    Normally settings.EMAIL_BACKEND is set to "django.core.mail.backends.locmem.EmailBackend" by django, 
+    along with mail.outbox = []. If this function doesn't run for whatever reason, the mailoutbox fixture will not work properly.
+    """
+    django_pytester.create_test_module(
+        """
+        import pytest
+
+        @pytest.fixture(autouse=True, scope="session")
+        def django_test_environment(request):
+            yield
+        """, filename="conftest.py"
+    )
+
+    django_pytester.create_test_module(
+        """
+        def test_bad_mail(settings, mailoutbox):
+            assert mailoutbox is None
+            assert settings.EMAIL_BACKEND == "django.core.mail.backends.dummy.EmailBackend"
+        """
+    )
+    result = django_pytester.runpytest_subprocess()
+    assert result.ret == 0

From c8c73550cf8d0786ecb38fa0e2f9914ade00eff4 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 12:19:29 +0200
Subject: [PATCH 12/23] Fixes linter

---
 pytest_django/plugin.py | 1 +
 tests/test_fixtures.py  | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index b479fefb..f99ea246 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -616,6 +616,7 @@ def mailoutbox(
 
     if hasattr(mail, "outbox"):
         return mail.outbox  # type: ignore[no-any-return]
+    return None
 
 
 @pytest.fixture()
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 4c98b899..f8ca69c7 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -837,7 +837,7 @@ def test_mail_auto_fixture_misconfigured(django_pytester: DjangoPytester) -> Non
     """
     django_test_environment fixture can be overridden by user, and that would break mailoutbox fixture.
 
-    Normally settings.EMAIL_BACKEND is set to "django.core.mail.backends.locmem.EmailBackend" by django, 
+    Normally settings.EMAIL_BACKEND is set to "django.core.mail.backends.locmem.EmailBackend" by django,
     along with mail.outbox = []. If this function doesn't run for whatever reason, the mailoutbox fixture will not work properly.
     """
     django_pytester.create_test_module(
@@ -847,7 +847,8 @@ def test_mail_auto_fixture_misconfigured(django_pytester: DjangoPytester) -> Non
         @pytest.fixture(autouse=True, scope="session")
         def django_test_environment(request):
             yield
-        """, filename="conftest.py"
+        """,
+        filename="conftest.py",
     )
 
     django_pytester.create_test_module(

From 4e26a87597231a9b4945017bb05e7f739fd01f68 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 12:29:43 +0200
Subject: [PATCH 13/23] Adds warning

---
 pytest_django/plugin.py | 6 +++++-
 tests/test_fixtures.py  | 7 ++++++-
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index f99ea246..faaa3535 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -593,7 +593,7 @@ def non_debugging_runtest(self) -> None:
 
 
 @pytest.fixture(autouse=True)
-def _dj_autoclear_mailbox() -> None:
+def _dj_autoclear_mailbox(request: pytest.FixtureRequest) -> None:
     if not django_settings_is_configured():
         return
 
@@ -601,6 +601,10 @@ def _dj_autoclear_mailbox() -> None:
 
     if hasattr(mail, "outbox"):
         mail.outbox.clear()
+    else:
+        request.node.warn(
+            pytest.PytestWarning("Error when trying to clear mailbox, possible misconfiguration")
+        )
 
 
 @pytest.fixture()
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index f8ca69c7..bf4fccf9 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -838,8 +838,12 @@ def test_mail_auto_fixture_misconfigured(django_pytester: DjangoPytester) -> Non
     django_test_environment fixture can be overridden by user, and that would break mailoutbox fixture.
 
     Normally settings.EMAIL_BACKEND is set to "django.core.mail.backends.locmem.EmailBackend" by django,
-    along with mail.outbox = []. If this function doesn't run for whatever reason, the mailoutbox fixture will not work properly.
+    along with mail.outbox = []. If this function doesn't run for whatever reason, the
+    mailoutbox fixture will not work properly.
     """
+    expected_warning_message = (
+        "PytestWarning: Error when trying to clear mailbox, possible misconfiguration"
+    )
     django_pytester.create_test_module(
         """
         import pytest
@@ -860,3 +864,4 @@ def test_bad_mail(settings, mailoutbox):
     )
     result = django_pytester.runpytest_subprocess()
     assert result.ret == 0
+    assert expected_warning_message in "\n".join(result.outlines)

From 5effbf7f348fcd62e4ca5b1fde8cb4e080d5941f Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 12:39:01 +0200
Subject: [PATCH 14/23] Test the warning

---
 tests/test_fixtures.py | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index bf4fccf9..8227ec84 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -857,11 +857,16 @@ def django_test_environment(request):
 
     django_pytester.create_test_module(
         """
-        def test_bad_mail(settings, mailoutbox):
+        def test_with_fixture(settings, mailoutbox):
             assert mailoutbox is None
             assert settings.EMAIL_BACKEND == "django.core.mail.backends.dummy.EmailBackend"
+
+        def test_without_fixture():
+            from django.core import mail
+            assert not hasattr(mail, "outbox")
         """
     )
-    result = django_pytester.runpytest_subprocess()
-    assert result.ret == 0
-    assert expected_warning_message in "\n".join(result.outlines)
+    result = django_pytester.runpytest_subprocess("-q")
+    output = "\n".join(result.outlines)
+    assert "2 passed, 2 warnings" in output
+    assert expected_warning_message in output

From c4a9a7b252ec5badcc6b888c36619f77290c0794 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Tue, 1 Apr 2025 13:00:21 +0200
Subject: [PATCH 15/23] ehh f-it. this is good enough

---
 tests/test_fixtures.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 8227ec84..db524cc6 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -868,5 +868,5 @@ def test_without_fixture():
     )
     result = django_pytester.runpytest_subprocess("-q")
     output = "\n".join(result.outlines)
-    assert "2 passed, 2 warnings" in output
+    assert "2 passed" in output
     assert expected_warning_message in output

From 1d7a61570769783c498e2f9bb7e760bd3896abdd Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 15:43:19 -0400
Subject: [PATCH 16/23] Adds test for when there is no 'settings' at all

---
 tests/conftest.py      |  7 ++++++-
 tests/test_fixtures.py | 22 ++++++++++++++++++++++
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index 16e209f1..1ef17498 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -30,11 +30,13 @@ def _marker_apifun(
     extra_settings: str = "",
     create_manage_py: bool = False,
     project_root: str | None = None,
+    has_settings: bool = True,
 ):
     return {
         "extra_settings": extra_settings,
         "create_manage_py": create_manage_py,
         "project_root": project_root,
+        "has_settings": has_settings,
     }
 
 
@@ -142,7 +144,10 @@ def django_pytester(
     pythonpath = os.pathsep.join(filter(None, [str(REPOSITORY_ROOT), os.getenv("PYTHONPATH", "")]))
     monkeypatch.setenv("PYTHONPATH", pythonpath)
 
-    monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.the_settings")
+    if options["has_settings"]:
+        monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.the_settings")
+    else:
+        monkeypatch.delenv("DJANGO_SETTINGS_MODULE", raising=False)
 
     def create_test_module(test_code: str, filename: str = "test_the_test.py") -> Path:
         r = tpkg_path.joinpath(filename)
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index db524cc6..500c34b0 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -870,3 +870,25 @@ def test_without_fixture():
     output = "\n".join(result.outlines)
     assert "2 passed" in output
     assert expected_warning_message in output
+
+
+@pytest.mark.django_project(has_settings=False)
+def test_no_settings(django_pytester: DjangoPytester) -> None:
+    django_pytester.create_test_module(
+        """
+        def test_skipped_settings(settings):
+            pass
+
+        def test_mailoutbox(mailoutbox):
+            assert mailoutbox is None
+
+        def test_mail():
+            from django.core import mail
+            assert not hasattr(mail, "outbox")
+        """
+    )
+    result = django_pytester.runpytest_subprocess("-v")
+    output = "\n".join(result.outlines)
+    assert "::test_skipped_settings SKIPPED" in output
+    assert "::test_mailoutbox PASSED" in output
+    assert "::test_mail PASSED" in output

From cf170faeff64ef9d0d966c622a42379b30064508 Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 15:46:14 -0400
Subject: [PATCH 17/23] Slight change to ensure that there really isnt any
 settings

---
 tests/conftest.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index 1ef17498..ea59945d 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -137,7 +137,8 @@ def django_pytester(
 
     # Copy the test app to make it available in the new test run
     shutil.copytree(str(app_source), str(test_app_path))
-    tpkg_path.joinpath("the_settings.py").write_text(test_settings)
+    if options["has_settings"]:
+        tpkg_path.joinpath("the_settings.py").write_text(test_settings)
 
     # For suprocess tests, pytest's `pythonpath` setting doesn't currently
     # work, only the envvar does.

From 534a7f2b7ed952d7b6c90fc8f7f9829619742c73 Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 16:06:22 -0400
Subject: [PATCH 18/23] Gigantic simplification

---
 pytest_django/plugin.py |  7 +------
 tests/test_fixtures.py  | 14 +++++---------
 2 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index faaa3535..e1d56156 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -601,10 +601,6 @@ def _dj_autoclear_mailbox(request: pytest.FixtureRequest) -> None:
 
     if hasattr(mail, "outbox"):
         mail.outbox.clear()
-    else:
-        request.node.warn(
-            pytest.PytestWarning("Error when trying to clear mailbox, possible misconfiguration")
-        )
 
 
 @pytest.fixture()
@@ -613,8 +609,7 @@ def mailoutbox(
     _dj_autoclear_mailbox: None,
 ) -> list[django.core.mail.EmailMessage] | None:
     """A clean email outbox to which Django-generated emails are sent."""
-    if not django_settings_is_configured():
-        return None
+    skip_if_no_django()
 
     from django.core import mail
 
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 500c34b0..0d6327ea 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -841,9 +841,6 @@ def test_mail_auto_fixture_misconfigured(django_pytester: DjangoPytester) -> Non
     along with mail.outbox = []. If this function doesn't run for whatever reason, the
     mailoutbox fixture will not work properly.
     """
-    expected_warning_message = (
-        "PytestWarning: Error when trying to clear mailbox, possible misconfiguration"
-    )
     django_pytester.create_test_module(
         """
         import pytest
@@ -869,7 +866,6 @@ def test_without_fixture():
     result = django_pytester.runpytest_subprocess("-q")
     output = "\n".join(result.outlines)
     assert "2 passed" in output
-    assert expected_warning_message in output
 
 
 @pytest.mark.django_project(has_settings=False)
@@ -877,10 +873,10 @@ def test_no_settings(django_pytester: DjangoPytester) -> None:
     django_pytester.create_test_module(
         """
         def test_skipped_settings(settings):
-            pass
+            assert False
 
-        def test_mailoutbox(mailoutbox):
-            assert mailoutbox is None
+        def test_skipped_mailoutbox(mailoutbox):
+            assert False
 
         def test_mail():
             from django.core import mail
@@ -890,5 +886,5 @@ def test_mail():
     result = django_pytester.runpytest_subprocess("-v")
     output = "\n".join(result.outlines)
     assert "::test_skipped_settings SKIPPED" in output
-    assert "::test_mailoutbox PASSED" in output
-    assert "::test_mail PASSED" in output
+    assert "::test_skipped_mailoutbox SKIPPED" in output
+    assert "::test_mail PASSED" in output
\ No newline at end of file

From b330a26929cf06d1cbdbdf6b86a94cf998c8db96 Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 16:08:10 -0400
Subject: [PATCH 19/23] Removes unused import

---
 pytest_django/plugin.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index e1d56156..f8e1d071 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -593,7 +593,7 @@ def non_debugging_runtest(self) -> None:
 
 
 @pytest.fixture(autouse=True)
-def _dj_autoclear_mailbox(request: pytest.FixtureRequest) -> None:
+def _dj_autoclear_mailbox() -> None:
     if not django_settings_is_configured():
         return
 

From 80303a447062ba1bba42d15893a30d876bd2df52 Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 16:15:38 -0400
Subject: [PATCH 20/23] Updates linter

---
 tests/test_fixtures.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 0d6327ea..62cb7f20 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -887,4 +887,4 @@ def test_mail():
     output = "\n".join(result.outlines)
     assert "::test_skipped_settings SKIPPED" in output
     assert "::test_skipped_mailoutbox SKIPPED" in output
-    assert "::test_mail PASSED" in output
\ No newline at end of file
+    assert "::test_mail PASSED" in output

From 3223687b2bd08b1f3cb016a6481df9f2c1d1152b Mon Sep 17 00:00:00 2001
From: kingbuzzman <buzzi.javier@gmail.com>
Date: Wed, 2 Apr 2025 17:10:38 -0400
Subject: [PATCH 21/23] Slight simplification when asserting tests

---
 tests/test_fixtures.py | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 62cb7f20..490dd8ef 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -863,9 +863,8 @@ def test_without_fixture():
             assert not hasattr(mail, "outbox")
         """
     )
-    result = django_pytester.runpytest_subprocess("-q")
-    output = "\n".join(result.outlines)
-    assert "2 passed" in output
+    result = django_pytester.runpytest_subprocess()
+    result.assert_outcomes(passed=2)
 
 
 @pytest.mark.django_project(has_settings=False)
@@ -883,8 +882,5 @@ def test_mail():
             assert not hasattr(mail, "outbox")
         """
     )
-    result = django_pytester.runpytest_subprocess("-v")
-    output = "\n".join(result.outlines)
-    assert "::test_skipped_settings SKIPPED" in output
-    assert "::test_skipped_mailoutbox SKIPPED" in output
-    assert "::test_mail PASSED" in output
+    result = django_pytester.runpytest_subprocess()
+    result.assert_outcomes(passed=1, skipped=2)

From 7acaee2530a4eb45acf4f6505e774d4f88273c8a Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Thu, 3 Apr 2025 16:11:12 -0400
Subject: [PATCH 22/23] Changes bluetech wanted

---
 pytest_django/plugin.py | 2 +-
 tests/conftest.py       | 8 ++++----
 tests/test_fixtures.py  | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/pytest_django/plugin.py b/pytest_django/plugin.py
index f8e1d071..e8e629f4 100644
--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -615,7 +615,7 @@ def mailoutbox(
 
     if hasattr(mail, "outbox"):
         return mail.outbox  # type: ignore[no-any-return]
-    return None
+    return []
 
 
 @pytest.fixture()
diff --git a/tests/conftest.py b/tests/conftest.py
index ea59945d..e3bfa1f4 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -30,13 +30,13 @@ def _marker_apifun(
     extra_settings: str = "",
     create_manage_py: bool = False,
     project_root: str | None = None,
-    has_settings: bool = True,
+    create_settings: bool = True,
 ):
     return {
         "extra_settings": extra_settings,
         "create_manage_py": create_manage_py,
         "project_root": project_root,
-        "has_settings": has_settings,
+        "create_settings": create_settings,
     }
 
 
@@ -137,7 +137,7 @@ def django_pytester(
 
     # Copy the test app to make it available in the new test run
     shutil.copytree(str(app_source), str(test_app_path))
-    if options["has_settings"]:
+    if options["create_settings"]:
         tpkg_path.joinpath("the_settings.py").write_text(test_settings)
 
     # For suprocess tests, pytest's `pythonpath` setting doesn't currently
@@ -145,7 +145,7 @@ def django_pytester(
     pythonpath = os.pathsep.join(filter(None, [str(REPOSITORY_ROOT), os.getenv("PYTHONPATH", "")]))
     monkeypatch.setenv("PYTHONPATH", pythonpath)
 
-    if options["has_settings"]:
+    if options["create_settings"]:
         monkeypatch.setenv("DJANGO_SETTINGS_MODULE", "tpkg.the_settings")
     else:
         monkeypatch.delenv("DJANGO_SETTINGS_MODULE", raising=False)
diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 490dd8ef..9d55ad6d 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -867,7 +867,7 @@ def test_without_fixture():
     result.assert_outcomes(passed=2)
 
 
-@pytest.mark.django_project(has_settings=False)
+@pytest.mark.django_project(create_settings=False)
 def test_no_settings(django_pytester: DjangoPytester) -> None:
     django_pytester.create_test_module(
         """

From 4975bc168b41c3a4951e108548a85ed815d31f28 Mon Sep 17 00:00:00 2001
From: Javier Buzzi <buzzi.javier@gmail.com>
Date: Thu, 3 Apr 2025 16:14:40 -0400
Subject: [PATCH 23/23] Update test_fixtures.py

---
 tests/test_fixtures.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/test_fixtures.py b/tests/test_fixtures.py
index 9d55ad6d..f88ed802 100644
--- a/tests/test_fixtures.py
+++ b/tests/test_fixtures.py
@@ -855,7 +855,7 @@ def django_test_environment(request):
     django_pytester.create_test_module(
         """
         def test_with_fixture(settings, mailoutbox):
-            assert mailoutbox is None
+            assert mailoutbox == []
             assert settings.EMAIL_BACKEND == "django.core.mail.backends.dummy.EmailBackend"
 
         def test_without_fixture():