Skip to content

Commit

Permalink
Setup application for repeated test runs.
Browse files Browse the repository at this point in the history
  • Loading branch information
ntoll committed Feb 17, 2020
1 parent e1490c3 commit ff8a114
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 29 deletions.
8 changes: 0 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,6 @@ test-random: ## Run the application tests in random order
xvfb-run $$TEST_CMD ; else \
$$TEST_CMD ; fi

FUNCTESTS ?= func_tests
.PHONY: func-test
func-test:
@TEST_CMD="python -m pytest -v --random-order-bucket=global $(TESTOPTS) $(FUNCTESTS)" ; \
if command -v xvfb-run > /dev/null; then \
xvfb-run $$TEST_CMD ; else \
$$TEST_CMD ; fi

.PHONY: lint
lint: ## Run the linters
@flake8 securedrop_client tests
Expand Down
2 changes: 2 additions & 0 deletions dev-requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pytest-cov==2.8.1
pytest-mock==1.10.0
pytest-qt==3.3.0
pytest-random-order==1.0.4
pytest-vcr==1.0.2
pytest-xdist==1.30.0
sip==4.19.8
typed-ast==1.3.4
vcrpy==4.0.2
60 changes: 60 additions & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,25 @@ more-itertools==4.3.0 \
--hash=sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092 \
--hash=sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e \
--hash=sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d
multidict==4.7.4 \
--hash=sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e \
--hash=sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c \
--hash=sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7 \
--hash=sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26 \
--hash=sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb \
--hash=sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703 \
--hash=sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a \
--hash=sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357 \
--hash=sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625 \
--hash=sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c \
--hash=sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c \
--hash=sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd \
--hash=sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d \
--hash=sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b \
--hash=sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4 \
--hash=sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7 \
--hash=sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51 \
# via yarl
mypy-extensions==0.4.1 \
--hash=sha256:37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812 \
--hash=sha256:b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e
Expand Down Expand Up @@ -165,6 +184,9 @@ pytest-qt==3.3.0 \
pytest-random-order==1.0.4 \
--hash=sha256:6b2159342a4c8c10855bc4fc6d65ee890fc614cb2b4ff688979b008a82a0ff52 \
--hash=sha256:72279a7f823969e18b10e438950f58330d17e0fcffb57cbd7929770cd687ecb2
pytest-vcr==1.0.2 \
--hash=sha256:23ee51b75abbcc43d926272773aae4f39f93aceb75ed56852d0bf618f92e1896 \
--hash=sha256:2f316e0539399bea0296e8b8401145c62b6f85e9066af7e57b6151481b0d6d9c
pytest-xdist==1.30.0 \
--hash=sha256:5d1b1d4461518a6023d56dab62fb63670d6f7537f23e2708459a557329accf48 \
--hash=sha256:a8569b027db70112b290911ce2ed732121876632fb3f40b1d39cd2f72f58b147
Expand All @@ -176,6 +198,19 @@ python-dateutil==2.7.5 \
--hash=sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02
python-editor==1.0.3 \
--hash=sha256:a3c066acee22a1c94f63938341d4fb374e3fdd69366ed6603d7b24bed1efc565
pyyaml==5.3 \
--hash=sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6 \
--hash=sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf \
--hash=sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5 \
--hash=sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e \
--hash=sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811 \
--hash=sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e \
--hash=sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d \
--hash=sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20 \
--hash=sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689 \
--hash=sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994 \
--hash=sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615 \
# via vcrpy
requests==2.20.0 \
--hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \
--hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279
Expand Down Expand Up @@ -224,10 +259,35 @@ typed-ast==1.3.4 \
urllib3==1.24.3 \
--hash=sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4 \
--hash=sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb
vcrpy==4.0.2 \
--hash=sha256:9740c5b1b63626ec55cefb415259a2c77ce00751e97b0f7f214037baaf13c7bf \
--hash=sha256:c4ddf1b92c8a431901c56a1738a2c797d965165a96348a26f4b2bbc5fa6d36d9
wcwidth==0.1.7 \
--hash=sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e \
--hash=sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c \
# via pytest
wrapt==1.11.2 \
--hash=sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1 \
# via vcrpy
yarl==1.4.2 \
--hash=sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce \
--hash=sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6 \
--hash=sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce \
--hash=sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae \
--hash=sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d \
--hash=sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f \
--hash=sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b \
--hash=sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b \
--hash=sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb \
--hash=sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462 \
--hash=sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea \
--hash=sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70 \
--hash=sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1 \
--hash=sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a \
--hash=sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b \
--hash=sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080 \
--hash=sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2 \
# via vcrpy
zipp==0.6.0 \
--hash=sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e \
--hash=sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335 \
Expand Down
21 changes: 0 additions & 21 deletions func_tests/test_client.py

This file was deleted.

File renamed without changes.
107 changes: 107 additions & 0 deletions tests/functional/test_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import os
import tempfile
import json
import pytest


from sqlalchemy.orm.exc import NoResultFound


from PyQt5.QtCore import Qt


from securedrop_client.gui.main import Window
from securedrop_client.logic import Controller
from securedrop_client.config import Config
from securedrop_client.gui.widgets import LoginDialog
from securedrop_client.db import Base, make_session_maker, ReplySendStatus, ReplySendStatusCodes
from securedrop_client.utils import safe_mkdir


HOSTNAME = "http://localhost:8081/"
USERNAME = "journalist"
PASSWORD = "correct horse battery staple profanity oil chewy"
OTP = "783682"


def get_safe_tempdir():
return tempfile.TemporaryDirectory()


def get_test_context(sdc_home, mocker):
"""
Returns a tuple containing a Window instance and a Controller instance that
have been correctly set up and isolated from any other instances of the
application to be run in the test suite.
"""
gui = Window() # The application's wind
# Create all app assets in a new temp directory and sub-directories.
safe_mkdir(os.path.join(sdc_home.name, "gpg"))
safe_mkdir(os.path.join(sdc_home.name, "data"))
# Configure and create the database.
session_maker = make_session_maker(sdc_home.name)
create_dev_data(sdc_home.name, session_maker)
# Create the controller.
controller = Controller(HOSTNAME, gui, session_maker, sdc_home.name,
False, False)
# Link the gui and controller together.
gui.controller = controller
# Et Voila...
with mocker.patch("securedrop_client.logic.sdclientapi") as mock_api:
return (gui, controller, mock_api)


def create_dev_data(sdc_home, session_maker):
"""
Based upon the functionality in the script, create_dev_data.py. This is
used to setup and configure the database and GPG keyring related metadata.
"""
session = session_maker()
Base.metadata.create_all(bind=session.get_bind())

with open(os.path.join(sdc_home, Config.CONFIG_NAME), 'w') as f:
f.write(json.dumps({
'journalist_key_fingerprint': '65A1B5FF195B56353CC63DFFCC40EF1228271441',
}))

for reply_send_status in ReplySendStatusCodes:
try:
reply_status = session.query(ReplySendStatus).filter_by(
name=reply_send_status.value).one()
except NoResultFound:
reply_status = ReplySendStatus(reply_send_status.value)
session.add(reply_status)
session.commit()


def test_login_ensure_errors_displayed(qtbot, mocker):
"""
We see an error if incomplete credentials are supplied to the login dialog.
"""
w = Window()
login_dialog = LoginDialog(w)
login_dialog.show()
assert login_dialog.error_bar.error_status_bar.text() == ""
qtbot.keyClicks(login_dialog.username_field, "journalist")
qtbot.mouseClick(login_dialog.submit, Qt.LeftButton)
expected = "Please enter a username, password and two-factor code."
actual = login_dialog.error_bar.error_status_bar.text()
assert actual == expected


def test_login_as_journalist(qtbot, mocker):
"""
The app is visible if the user logs in with apparently correct credentials.
"""
tempdir = get_safe_tempdir() # Once out of scope, is deleted.
gui, controller, mock_api = get_test_context(tempdir, mocker)
login_dialog = LoginDialog(gui)
login_dialog.setup(controller)
gui.login_dialog = login_dialog
login_dialog.show()
assert login_dialog.error_bar.error_status_bar.text() == ""
qtbot.keyClicks(login_dialog.username_field, USERNAME)
qtbot.keyClicks(login_dialog.password_field, PASSWORD)
qtbot.keyClicks(login_dialog.tfa_field, OTP)
qtbot.mouseClick(login_dialog.submit, Qt.LeftButton)
assert gui.isVisible()

0 comments on commit ff8a114

Please sign in to comment.