Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #24 from freedomofpress/native-pytest-infra
Browse files Browse the repository at this point in the history
Use native pytest infrastructure
  • Loading branch information
legoktm authored Feb 14, 2023
2 parents 39d75f1 + 542108b commit bb98fb7
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 366 deletions.
Empty file added tests/__init__.py
Empty file.
78 changes: 35 additions & 43 deletions tests/test_notify.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import datetime
import os
import re
from importlib.machinery import SourceFileLoader
from unittest import mock

import pytest

relpath_notify = "../sdw_notify/Notify.py"
path_to_notify = os.path.join(os.path.dirname(os.path.abspath(__file__)), relpath_notify)
notify = SourceFileLoader("Notify", path_to_notify).load_module()

relpath_updater = "../sdw_updater/Updater.py"
path_to_updater = os.path.join(os.path.dirname(os.path.abspath(__file__)), relpath_updater)
updater = SourceFileLoader("Updater", path_to_updater).load_module()

from sdw_notify import Notify
from sdw_updater import Updater

# Regex for warning log if the last-updated timestamp does not exist (updater
# has never run)
Expand Down Expand Up @@ -41,18 +33,18 @@
BAD_TIMESTAMP_REGEX = r"Data in .* not in the expected format."


@mock.patch("Notify.sdlog.error")
@mock.patch("Notify.sdlog.warning")
@mock.patch("Notify.sdlog.info")
def test_warning_shown_if_updater_never_ran(mocked_info, mocked_warning, mocked_error, tmpdir):
@mock.patch("sdw_notify.Notify.sdlog.error")
@mock.patch("sdw_notify.Notify.sdlog.warning")
@mock.patch("sdw_notify.Notify.sdlog.info")
def test_warning_shown_if_updater_never_ran(mocked_info, mocked_warning, mocked_error, tmp_path):
"""
Test whether we're correctly going to show a warning if the updater has
never run.
"""
# We're going to look for a nonexistent file in an existing tmpdir
with mock.patch("Notify.LAST_UPDATED_FILE", os.path.join(tmpdir, "not-a-file")):
# We're going to look for a nonexistent file in an existing temporary directoryr
with mock.patch("sdw_notify.Notify.LAST_UPDATED_FILE", tmp_path / "not-a-file"):

warning_should_be_shown = notify.is_update_check_necessary()
warning_should_be_shown = Notify.is_update_check_necessary()

# No handled errors should occur
assert not mocked_error.called
Expand All @@ -70,29 +62,29 @@ def test_warning_shown_if_updater_never_ran(mocked_info, mocked_warning, mocked_

@pytest.mark.parametrize(
"uptime,warning_expected",
[(notify.UPTIME_GRACE_PERIOD + 1, True), (notify.UPTIME_GRACE_PERIOD - 1, False)],
[(Notify.UPTIME_GRACE_PERIOD + 1, True), (Notify.UPTIME_GRACE_PERIOD - 1, False)],
)
@mock.patch("Notify.sdlog.error")
@mock.patch("Notify.sdlog.warning")
@mock.patch("Notify.sdlog.info")
@mock.patch("sdw_notify.Notify.sdlog.error")
@mock.patch("sdw_notify.Notify.sdlog.warning")
@mock.patch("sdw_notify.Notify.sdlog.info")
def test_warning_shown_if_warning_threshold_exceeded(
mocked_info, mocked_warning, mocked_error, tmpdir, uptime, warning_expected
mocked_info, mocked_warning, mocked_error, tmp_path, uptime, warning_expected
):
"""
Primary use case for the notifier: are we showing the warning if the
system hasn't been (successfully) updated for longer than the warning
threshold? Expected result varies based on whether system uptime exceeds
a grace period (for the user to launch the app on their own).
"""
with mock.patch("Notify.LAST_UPDATED_FILE", os.path.join(tmpdir, "sdw-last-updated")):
with mock.patch("sdw_notify.Notify.LAST_UPDATED_FILE", tmp_path / "sdw-last-updated"):
# Write a "last successfully updated" date well in the past for check
historic_date = datetime.date(2013, 6, 5).strftime(updater.DATE_FORMAT)
with open(notify.LAST_UPDATED_FILE, "w") as f:
historic_date = datetime.date(2013, 6, 5).strftime(Updater.DATE_FORMAT)
with open(Notify.LAST_UPDATED_FILE, "w") as f:
f.write(historic_date)

with mock.patch("Notify.get_uptime_seconds") as mocked_uptime:
with mock.patch("sdw_notify.Notify.get_uptime_seconds") as mocked_uptime:
mocked_uptime.return_value = uptime
warning_should_be_shown = notify.is_update_check_necessary()
warning_should_be_shown = Notify.is_update_check_necessary()
assert warning_should_be_shown is warning_expected
# No handled errors should occur
assert not mocked_error.called
Expand All @@ -108,42 +100,42 @@ def test_warning_shown_if_warning_threshold_exceeded(
assert re.search(GRACE_PERIOD_REGEX, info_string) is not None


@mock.patch("Notify.sdlog.error")
@mock.patch("Notify.sdlog.warning")
@mock.patch("Notify.sdlog.info")
@mock.patch("sdw_notify.Notify.sdlog.error")
@mock.patch("sdw_notify.Notify.sdlog.warning")
@mock.patch("sdw_notify.Notify.sdlog.info")
def test_warning_not_shown_if_warning_threshold_not_exceeded(
mocked_info, mocked_warning, mocked_error, tmpdir
mocked_info, mocked_warning, mocked_error, tmp_path
):
"""
Another high priority case: we don't want to warn the user if they've
recently run the updater successfully.
"""
with mock.patch("Notify.LAST_UPDATED_FILE", os.path.join(tmpdir, "sdw-last-updated")):
with mock.patch("sdw_notify.Notify.LAST_UPDATED_FILE", tmp_path / "sdw-last-updated"):
# Write current timestamp into the file
just_now = datetime.datetime.now().strftime(updater.DATE_FORMAT)
with open(notify.LAST_UPDATED_FILE, "w") as f:
just_now = datetime.datetime.now().strftime(Updater.DATE_FORMAT)
with open(Notify.LAST_UPDATED_FILE, "w") as f:
f.write(just_now)
warning_should_be_shown = notify.is_update_check_necessary()
warning_should_be_shown = Notify.is_update_check_necessary()
assert warning_should_be_shown is False
assert not mocked_error.called
assert not mocked_warning.called
info_string = mocked_info.call_args[0][0]
assert re.search(NO_WARNING_REGEX, info_string) is not None


@mock.patch("Notify.sdlog.error")
@mock.patch("Notify.sdlog.warning")
@mock.patch("Notify.sdlog.info")
def test_corrupt_timestamp_file_handled(mocked_info, mocked_warning, mocked_error, tmpdir):
@mock.patch("sdw_notify.Notify.sdlog.error")
@mock.patch("sdw_notify.Notify.sdlog.warning")
@mock.patch("sdw_notify.Notify.sdlog.info")
def test_corrupt_timestamp_file_handled(mocked_info, mocked_warning, mocked_error, tmp_path):
"""
The LAST_UPDATED_FILE must contain a timestamp in a specified format;
if it doesn't, we show the warning and log the error.
"""
with mock.patch("Notify.LAST_UPDATED_FILE", os.path.join(tmpdir, "sdw-last-updated")):
with open(notify.LAST_UPDATED_FILE, "w") as f:
with mock.patch("sdw_notify.Notify.LAST_UPDATED_FILE", tmp_path / "sdw-last-updated"):
with open(Notify.LAST_UPDATED_FILE, "w") as f:
# With apologies to HAL 9000
f.write("daisy, daisy, give me your answer do")
warning_should_be_shown = notify.is_update_check_necessary()
warning_should_be_shown = Notify.is_update_check_necessary()
assert warning_should_be_shown is True
mocked_error.assert_called_once()
error_string = mocked_error.call_args[0][0]
Expand All @@ -154,6 +146,6 @@ def test_uptime_is_sane():
"""
Even in a CI container this should be greater than zero :-)
"""
seconds = notify.get_uptime_seconds()
seconds = Notify.get_uptime_seconds()
assert isinstance(seconds, float)
assert seconds > 0
Loading

0 comments on commit bb98fb7

Please sign in to comment.