-
Notifications
You must be signed in to change notification settings - Fork 42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial code for functional tests. #788
Conversation
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.
so for the network mocking, one good place to look is this test data (since we'll need to take a similar approach here) in the securedrop-sdk repository here: https://github.com/freedomofpress/securedrop-sdk/tree/master/data (JSON for connections to the server via securedrop-proxy, YAML are vcr.py cassettes for direct HTTP connections). In this repo, I think we'd want to:
- mock calls to securedrop-sdk/sdclientapi for the purpose of running the functional tests. This makes sense for devs locally running these tests as the server behavior will be constant, but the functional tests should catch issues that are less tied to the implementation.
- (at a later point) run these tests as integration tests: we'd run the client's functional tests with proxy=False against the server container in a CI job. We actually have this already rigged up in CI for the SDK: https://circleci.com/gh/freedomofpress/securedrop-sdk/681. We start up the server container, populate it with a bunch of sources/submissions/replies, and run the tests against it (this is done in order to check that the latest version of the SDK works against the latest version of the API at the time of merge).
Thoughts welcome @kushaldas @zenmonkeykstop or others on this
@redshiftzero ack on all your comments. I'll move the functional tests as you suggest, revise the Makefile, undo the mocks (more a habitual first stab - totally agree with your reasoning), have a go at vcr.py things and check out the description of https://github.com/freedomofpress/securedrop-client/wiki/Test-plan#basic-client-testing as a basis for the tests themselves. |
So I've just discovered that the registering of widgets with I.e. DO NOT DO THIS (my mistake):
The |
I want to give an update to my work so far.
I've pushed the WiP, which I'll continue with on Monday unless otherwise instructed. Feedback welcome. 👍 |
BTW... I expect this branch (at the moment) not to build (yet). |
Good news..! I think we've a solution for functional tests. Put simply, there are three aspects to the functional tests which interact with each other in sometimes non-obvious ways. It took several failed attempts as spikes, but this effort was needed to explore the context in order to find the solution presented in this PR. The three aspects are:
Some interesting asides that you should be aware of:
Next steps: I'll remove the "draft" status from the PR since we have a working solution..! However, I'll continue to add tests based on the afore referenced test plan since I get the feeling that further edge cases and gotchas will reveal themselves as more complicated test cases are implemented. At time of writing checking for login form errors and successful logging in are the only tests completed. |
I've been asked a couple of questions, which I'll answer here so there's a log of the answers: What happened regarding the issues with multi-threaded support for vcrpy?It turns out several things made this hard to resolve:
Any theories why the crash/core dump occurs at the end of the test execution?There were several crashes / core dumps / problems:
I've added comments to the functions I've created in the functional tests so folks just need to read the code to see what to do. This discussion on GitHub is just so folks can discover why the tests work in the way they do. One final "gotcha" I want to highlight is that Finally, everything should "just work" ™️ via I'll continue to add further functional tests as per the specs. More feedback welcome..! 👍 |
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 is amazingly simple.
Further updates:
|
Progress report for today. I created a bash script to further isolate the tests from each other and added a whole bunch of tests. The current coverage of functional tests to date is:
The remaining tests are offline versions of existing tests to be run as if the client is online (meaning I'll be able to re-use some of the UI driving code). It's close..! 👍 |
OK. I've finished adding all the test cases described in the checklist. Rebased with master. Feedback welcome. 🎉 😌 I'll demo / talk through this on Friday's call. 👍 |
I just timeboxed a couple of hours to try to recreate the test fails we saw in Friday's demo. Sadly, the damn things work as expected. From the tracebacks I had on Friday the errors were for basically for SQLite not being able to find/read/write to/from the file it was using as part of the client. I can only assume this is down to file permissions or something like that isolated to my dev machine (I had had problems with it that afternoon which required me to do an update and reboot). In any case, I'm not able to recreate the fails today. |
466d83f
to
9a3c8df
Compare
just gave this a little rebase before i begin review |
3bf591f
to
2ac8c62
Compare
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.
I see a segfault when I run make test-functional
. I'll provide details in a separate comment. I was able to run tests individually by running python -m pytest -v tests/functional/test_delete_source.py
for example. It looks like some tests fail because they just need to be updated to include recent changes to the client. I did come across other tests that failed with unexpected errors, such as test_delete_source.py
:
ERROR securedrop_client.queue:queue.py:131 CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/home/creviera/workspace/freedomofpress/securedrop-client/tests/functional/cassettes/test_delete_source_and_their_docs.yaml') in your current record mode ('once').
No match for the request (<Request (DELETE) http://localhost:8081/api/v1/sources/fb800891-09a8-4482-94c9-b516c5960b90>) was found.
Found 1 similar requests with 1 different matcher(s) :
1 - (<Request (DELETE) http://localhost:8081/api/v1/sources/2145abc6-367f-4d32-807b-06c5b2a42f3c>).
Matchers succeeded : ['method', 'scheme', 'host', 'port', 'query']
Matchers failed :
path - assertion failure :
/api/v1/sources/fb800891-09a8-4482-94c9-b516c5960b90 != /api/v1/sources/2145abc6-367f-4d32-807b-06c5b2a42f3c
if command -v xvfb-run > /dev/null; then \ | ||
xvfb-run $$TEST_CMD ; else \ | ||
xvfb-run -a $$TEST_CMD ; else \ |
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.
👍 allows us to run concurrent builds
Here are details on the
|
Also, forgot to include that I see test errors in CI (since these happen in random order and I only ran CI twice, there could be more errors): |
@creviera OK... I've been poking at this, this morning. There are two aspects to this:
This'll take some time and probably shouldn't happen until after the changes to the client have settled down (we currently have lots of things in flight). I also can't help but wonder about the overhead such functional tests will introduce in terms of maintaining / updating this code given such ongoing changes. I suspect when the client is in "business as usual" mode these tests will be very helpful for both checking things work as expected but also to encode key user journeys through the app. |
@kushaldas what does your environment look like? I wonder what's different between your development environment and mine? Here's what I did to set up my environment:
(see #788 (comment)) |
Looks like the problem with my dev environment was my version of
I tested that running
|
45afe1c
to
9e07519
Compare
👍 I think this can be merged after @creviera dismisses her review and it's rebased one last time. |
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.
read through the latest version of this diff, looks great! I dropped a couple of minor comments as I was reading through but I think if @rmol and @creviera are cool with it we should merge as is and address anything else including my comments (unless someone finds major issues) in followups
PASSWORD = "correct horse battery staple profanity oil chewy" | ||
|
||
|
||
def get_safe_tempdir(): |
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 use the existing tmpdir
fixture in pytest here?
def wait_for_login(): | ||
assert gui.login_dialog is None | ||
|
||
qtbot.waitUntil(wait_for_login, timeout=10000) |
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: for readability we could put the common timeout values we're using in the tests (at least 1000, 10000) into a common place in this utils files as named constants we can reuse e.g. TIMEOUT_SOURCELIST_RENDER
, TIMEOUT_LOGIN
…messages, starring and unstarring.
Updated all the tests and also VCR cassets for the latest master code.
9e07519
to
35ca550
Compare
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.
tests are all passing! lgtm:)
Description
REQUESTING FEEDBACK
Fixes #381.
The work done so far on this branch adds the scaffolding for functional tests using the
pytest-qt
plugin (see: https://pytest-qt.readthedocs.io/en/latest/intro.html). TL;DR It works, my approach and coding decisions need checking/feedback from the wider dev group and we should add more tests..!Please take a look and I'd love feedback via the comments. Work / decisions done so far.
pytest-qt
since this seems to be the obvious choice, it's well documented, and I know at least two of the core maintainers and they're good developers who I trust (i.e. this will be a good choice).Makefile
to include afunc-test
option. This runs the functional tests found in thefunc_tests
folder.func-test
target tomake check
. Thexvfb
command fails since it's already running (i.e. bothtest-random
andfunc-test
usexvfb
). Not sure how to fix this, but open to suggestions.make func-test
works well and I've decided to put functional tests into their own folder since I don't want to pollute the unit tests (found in thetests
folder) withtest_*
files that don't mirror the source code in the application. This can, of course, be very easily changed and is just an aesthetic decision on my part.Test Plan
Make sure you have the latest dev-requirements and then:
make func-test
A single functional test exercising the login dialog should pass. You should NOT see and widgets on your screen thanks to
xvfb
.Checklist
If these changes modify code paths involving cryptography, the opening of files in VMs or network (via the RPC service) traffic, Qubes testing in the staging environment is required. For fine tuning of the graphical user interface, testing in any environment in Qubes is required. Please check as applicable:
If these changes add or remove files other than client code, packaging logic (e.g., the AppArmor profile) may need to be updated. Please check as applicable: