-
Notifications
You must be signed in to change notification settings - Fork 16
Use pytest without unittest's TestCase class #151
Conversation
e433467
to
20bc2af
Compare
- Rely on datasaver to provide API token - Avoid retry logic in proxy tests -- without a way to exclude sleeps from the cassettes, there's very little value in automatically retrying TOTP tokens - Remove logout.txt logic as we currently don't need it
I've moved this to "Ready for review", but it's still a draft; I've observed some odd behavior where it sometimes re-fetches a token when it doesn't need to, which I'd like to debug a bit more. I'd appreciate some initial comments on the changes/simplifications, especially to the API proxy tests. |
Are you saying we have to be careful here because we will generate a cassette for the run of the test with the first parameter and then skip cassette generation for runs with the second and any other following parameters? |
Skip, or overwrite - either is bad if we expect different API response data for differently parametrized tests. Ideally, I think, we'd be able to stash the result for differently parametrized tests as separate cassettes, each with a unique filename. So if you have a |
Gotcha. Well so far code review looks good so tomorrow I'll run though cassette generation on qubes following the docs to make sure all goes smoothly. |
CI will fail until freedomofpress/securedrop#5667 is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
things are looking good but the readme instructions no longer work around regenerating cassettes so that just needs an update.
@@ -22,7 +22,7 @@ class TestAPIProxy(TestShared): | |||
""" | |||
|
|||
@dastollervey_datasaver | |||
def setUp(self): | |||
def setup_method(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we call this setup instead of setup_method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method name is designated by pytest
for the setup that runs before each test in class-based tests:
https://docs.pytest.org/en/stable/xunit_setup.html#method-and-function-level-setup-teardown
|
||
# Let us remove the temporary directory | ||
shutil.rmtree(tmpdir) | ||
|
||
# ORDER MATTERS: The following tests add or delete data, and should |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💎
save_auth(self.api.token) | ||
break | ||
|
||
@qrexec_datasaver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding the datasaver decorator here makes it so that the readme instructions are no longer accurate. on main
you'll see that you can follow these steps from the readme:
[Skip if adding a new test] Delete the cassettes you wish to regenerate or just delete all json files by running:
rm data/*.json
Comment out the
@qrexec_datasaver
decorator above the test you want to generate a new cassette for or just generate all new cassettes by commenting out the decorator above all methods in thetest_apiproxy.py::TestAPIProxy
class.Make qrexec calls to the server and collect real response data:
make test TESTS=tests/test_apiproxy.py
Perhaps this no longer works because of adding the decorator here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I think it's because we're no longer conditionally loading a recorded token based on the presence of a testtoken.json
file on disk, which means that re-running an individual test without commenting out qrexec_datasaver
for setup_method
will not work (because it'll replay the last token during that test's setup). Will verify and clarify.
It's not necessary to comment/uncomment the datasaver; just deleting JSON files will cause it to regenerate them if needed. However, it is necessary to get a fresh token whenever you're running tests that require it.
global CALLNUMBER | ||
global RES | ||
# This is the filename to store the results | ||
filename = os.path.join("data", func.__name__ + ".json") | ||
# if the logout.txt file is there, means we have a logout scenario |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was this never necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discussed out-of-band some ideas about making tests less brittle so that we can run them in random order in the future. for now, since the logout test will be the last test to run, this code is fine to remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking the time to understand the nitty gritty of how this works. The code is easier to read and cassette generation is faster now that you've removed the unnecessary step of commenting out the datasaver decorator.
🚢
Status
Ready for review
Fixes #152
Description
Switch to pytest
We were previously inheriting from unittest's
TestCase
class, which did not convey obvious benefits but conflicted with the use of pytest features like parametrization:This PR avoids inheriting from
TestCase
, and switches us to the leanerpytest
approach to validating assertions. We can now also usepytest
decorators likepytest.mark.parametrize
(though we'll still have to be careful regarding interaction with VCR cassettes, which is why I've not done so here yet).Simplifications of API proxy tests
logout.txt
logic as we currently don't need itqrexec_datasaver
Clearer error handling when proxy is missing or malfunctioning
If the proxy package is not installed in the target VM, the SDK would previously just fail with "Error parsing JSON". We now raise a more specific error message if we get no response on
stdout
.Test ordering
New configuration file location
Testing
Attempt to re-generate JSON and YML files by following the instructions in the revised README. Are you able to reliably run the test suite? Do the cassette recordings match your expectations for a given test? Do the requests you see to your SecureDrop Core development environment match what you're expect on initial run and playback?
Attempt to immediately regenerate JSON recordings after having done so once, to trigger a TOTP authentication failure. Is the error message clear and sufficient?