Open pepoluan opened 4 years ago
Try with:
@pytest.fixture
def temp_loop() -> asyncio.AbstractEventLoop:
default_loop = asyncio.get_event_loop()
new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)
try:
yield new_loop
finally:
new_loop.close()
asyncio.set_event_loop(default_loop)
@pytest.fixture
def decoding_controller(temp_loop):
controller = DecodingController(Sink, loop=temp_loop)
controller.start()
temp_loop.call_later(3.0, temp_loop.stop)
#
print("@@@ yielding @@@")
try:
yield controller
else:
#
print("@@@ returning @@@")
finally:
controller.stop()
Failing to clean up on failure can cause all kinds of weird and hard-to-identify issues. If that doesn't fix it someone else will have to help though :sweat_smile:
@Zac-HD so I implemented your suggestion (except for the else:
clause in decoding_controller
-- need an except:
if I want to use else
there)
The fixtures are now as such:
@pytest.fixture
def temp_loop() -> asyncio.AbstractEventLoop:
default_loop = asyncio.get_event_loop()
new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)
try:
#
print("!!! new loop !!!")
yield new_loop
#
finally:
print("!!! return to default_loop !!!")
new_loop.close()
asyncio.set_event_loop(default_loop)
@pytest.fixture
def decoding_controller(temp_loop):
controller = DecodingController(Sink, loop=temp_loop)
controller.start()
temp_loop.call_later(3.0, temp_loop.stop)
try:
#
print("@@@ yielding @@@")
yield controller
#
finally:
print("@@@ returning @@@")
controller.stop()
@pytest.fixture
def client():
print(">>> entering <<<")
with SMTP(*SERVER_ADDRESS) as smtp_client:
yield smtp_client
print(">>> exited <<<")
Executing:
(aiosmtpd-11-cp36) C:\Repos\aiosmtpd>pytest -vvvv -s aiosmtpd\tests\test_smtp_problem.py
=========================================== test session starts ===========================================
platform win32 -- Python 3.6.8, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- c:\repos\venvs\aiosmtpd-11-cp36\scr
ipts\python.exe
cachedir: .pytest_cache
rootdir: C:\Repos\aiosmtpd
plugins: mock-3.3.1
collected 1 item
aiosmtpd/tests/test_smtp_problem.py::TestSMTPNieuw::test_data_abortconn !!! new loop !!!
@@@ yielding @@@
>>> entering <<<
###SENDING_DATA###
FAILED
No joy. pytest still got stuck after printing "FAILED". Can't Ctrl-C, had to kill.
Just to add, replacing the line
assert code == 250 # I purposefully fail here
with
if code != 250:
pytest.fail()
also hangs.
Somehow pytest just got stuck there and never call any finalizers.
Just to add: Running in a standalone PowerShell 7 window (in a virtualenv) also hangs; but this time I can Ctrl-Break to terminate the process. (Ctrl-C still not working)
(test15) PS C:\Repos\aiosmtpd> pytest -vvv -s .\aiosmtpd\tests\test_smtp_problem.py
==================================================================== test session starts =====================================================================
platform win32 -- Python 3.8.2, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- c:\python\envs\test15\scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Repos\aiosmtpd
collected 1 item
aiosmtpd/tests/test_smtp_problem.py::TestSMTPNieuw::test_data_abortconn !!! new loop !!!
@@@ yielding @@@
>>> entering <<<
###SENDING_DATA###
FAILED
Update: Currently I'll use this workaround in the test case:
@pytest.mark.usefixtures("decoding_controller")
class TestSMTPNieuw:
def test_data_abortconn(self, decoding_controller, client):
print("###SENDING_HELO###")
code, _ = client.helo("example.com")
assert code == 250
print("###SENDING_MAIL###")
code, _ = client.docmd("MAIL FROM: <alice@example.org>")
assert code == 250
print("###SENDING_RCPT###")
code, _ = client.docmd("RCPT TO: <bob@example.org>")
assert code == 250
print("###SENDING_DATA###")
code, _ = client.docmd("DATA")
decoding_controller.stop()
assert code == 250 # This purposefully fails
print("###ASSERT_SUCCESS###")
Result:
============================ test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- c:\rep
os\venvs\aiosmtpd-11-cp36\scripts\python.exe
cachedir: .pytest_cache
rootdir: C:\Repos\aiosmtpd
plugins: mock-3.3.1
collected 1 item
aiosmtpd/tests/test_smtp_problem.py::TestSMTPNieuw::test_data_abortconn !!! new
loop !!!
@@@ yielding @@@
>>> entering <<<
###SENDING_HELO###
###SENDING_MAIL###
###SENDING_RCPT###
###SENDING_DATA###
FAILED>>> exited <<<
@@@ returning @@@
@@@ already stopped @@@
!!! return to default_loop !!!
================================== FAILURES ==================================
_____________________ TestSMTPNieuw.test_data_abortconn ______________________
self = <aiosmtpd.tests.test_smtp_problem.TestSMTPNieuw object at 0x000001AF0E30
BE10>
decoding_controller = <aiosmtpd.tests.test_smtp_problem.DecodingController obje
ct at 0x000001AF0E331160>
client = <smtplib.SMTP object at 0x000001AF0E331320>
def test_data_abortconn(self, decoding_controller, client):
print("###SENDING_HELO###")
code, _ = client.helo("example.com")
assert code == 250
print("###SENDING_MAIL###")
code, _ = client.docmd("MAIL FROM: <alice@example.org>")
assert code == 250
print("###SENDING_RCPT###")
code, _ = client.docmd("RCPT TO: <bob@example.org>")
assert code == 250
print("###SENDING_DATA###")
code, _ = client.docmd("DATA")
decoding_controller.stop()
> assert code == 250 # This purposefully fails
E assert 354 == 250
E +354
E -250
aiosmtpd\tests\test_smtp_problem.py:84: AssertionError
========================== short test summary info ===========================
FAILED aiosmtpd/tests/test_smtp_problem.py::TestSMTPNieuw::test_data_abortconn
============================= 1 failed in 0.13s ==============================
(aiosmtpd-11-cp36) C:\Repos\aiosmtpd>
(This requires an adaptation in the fixture because controller does not like .stop() to be called twice.)
So again this seems that for some reasons pytest does not call the finalizer for the decoding_controller
fixture during the first version's assertion fail.
Update: Wrapping the test steps in try...finally
also works:
@pytest.mark.usefixtures("decoding_controller")
class TestSMTPNieuw:
def test_data_abortconn(self, decoding_controller, client):
try:
print("###SENDING_HELO###")
code, _ = client.helo("example.com")
assert code == 250
print("###SENDING_MAIL###")
code, _ = client.docmd("MAIL FROM: <alice@example.org>")
assert code == 250
print("###SENDING_RCPT###")
code, _ = client.docmd("RCPT TO: <bob@example.org>")
assert code == 250
print("###SENDING_DATA###")
code, _ = client.docmd("DATA")
assert code == 250 # This purposefully fails
print("###ASSERT_SUCCESS###")
finally:
decoding_controller.stop()
same issue here!! my problem is that it randomly occurs - also just happening when more than one test module is executed by pytest. executing with python3 -m unittest no issue at all. version is - 6.2.5
Detailed Description
I'm writing pytest test cases for aiosmtpd, and I'm hitting this problem against
master
in aio-libs/aiosmtpdMinimal reproducible bug as follows:
Running the above inside PyCharm's Terminal window produces this:
... then pytest just got stuck there, not responding to anything, I can't even do Ctrl-C and I have to terminate the Terminal process.
pip list
(I actually only installed 3 packages:
atpublic
,pytest
, andpytest-mock
; the other packages are the dependencies of those three.)pytest & OS versions
Minimal example
See "Detailed Description" above
pip list
from the virtual environment you are using