Skip to content
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

tests: convert QPC CLI tests to pytests #263

Merged
merged 7 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Test the CLI module."""

import json
import logging
import os
import sys
import time
import unittest
from argparse import ArgumentParser, Namespace # noqa: I100
from io import StringIO # noqa: I100
from unittest.mock import patch

import pytest
import requests_mock

from qpc import messages
Expand All @@ -21,7 +22,7 @@
from qpc.utils import create_tar_buffer, get_server_location, write_server_config


class ReportDetailsTests(unittest.TestCase):
class TestReportDetails:
"""Class for testing the details report command."""

def _init_command(self):
Expand All @@ -30,7 +31,7 @@ def _init_command(self):
subparser = argument_parser.add_subparsers(dest="subcommand")
return ReportDetailsCommand(subparser)

def setUp(self):
def setup_method(self, _test_method):
"""Create test setup."""
# different from most other test cases where command is initialized once per
# class, this one requires to be initialized for each test method because
Expand All @@ -46,7 +47,7 @@ def setUp(self):
self.test_csv_filename = f"test_{time.time():.0f}.csv"
sys.stderr = HushUpStderr()

def tearDown(self):
def teardown_method(self):
"""Remove test setup."""
# Restore stderr
sys.stderr = self.orig_stderr
Expand All @@ -59,7 +60,7 @@ def tearDown(self):
except FileNotFoundError:
pass

def test_detail_report_as_json(self):
def test_detail_report_as_json(self, caplog):
"""Testing retrieving detail report as json."""
get_scanjob_url = get_server_location() + SCAN_JOB_URI + "1"
get_scanjob_json_data = {"id": 1, "report_id": 1}
Expand All @@ -84,15 +85,15 @@ def test_detail_report_as_json(self):
path=self.test_json_filename,
mask=False,
)
with self.assertLogs(level="INFO") as log:
with caplog.at_level(logging.INFO):
self.command.main(args)
self.assertIn(messages.REPORT_SUCCESSFULLY_WRITTEN, log.output[-1])
assert messages.REPORT_SUCCESSFULLY_WRITTEN in caplog.text
with open(self.test_json_filename, "r", encoding="utf-8") as json_file:
data = json_file.read()
file_content_dict = json.loads(data)
self.assertDictEqual(get_report_json_data, file_content_dict)
assert get_report_json_data == file_content_dict

def test_detail_report_as_json_report_id(self):
def test_detail_report_as_json_report_id(self, caplog):
"""Testing retrieving detail report as json with report id."""
get_report_url = get_server_location() + REPORT_URI + "1/details/"
get_report_json_data = {"id": 1, "report": [{"key": "value"}]}
Expand All @@ -114,15 +115,15 @@ def test_detail_report_as_json_report_id(self):
path=self.test_json_filename,
mask=False,
)
with self.assertLogs(level="INFO") as log:
with caplog.at_level(logging.INFO):
self.command.main(args)
self.assertIn(messages.REPORT_SUCCESSFULLY_WRITTEN, log.output[-1])
assert messages.REPORT_SUCCESSFULLY_WRITTEN in caplog.text
with open(self.test_json_filename, "r", encoding="utf-8") as json_file:
data = json_file.read()
file_content_dict = json.loads(data)
self.assertDictEqual(get_report_json_data, file_content_dict)
assert get_report_json_data == file_content_dict

def test_detail_report_as_csv(self):
def test_detail_report_as_csv(self, caplog):
"""Testing retrieving detail report as csv."""
get_scanjob_url = get_server_location() + SCAN_JOB_URI + "1"
get_scanjob_json_data = {"id": 1, "report_id": 1}
Expand Down Expand Up @@ -150,24 +151,24 @@ def test_detail_report_as_csv(self):
path=self.test_csv_filename,
mask=False,
)
with self.assertLogs(level="INFO") as log:
with caplog.at_level(logging.INFO):
self.command.main(args)
self.assertIn(messages.REPORT_SUCCESSFULLY_WRITTEN, log.output[-1])
assert messages.REPORT_SUCCESSFULLY_WRITTEN in caplog.text
with open(self.test_csv_filename, "r", encoding="utf-8") as json_file:
data = json_file.read()
file_content_dict = json.loads(data)
self.assertDictEqual(get_report_csv_data, file_content_dict)
assert get_report_csv_data == file_content_dict

# Test validation
def test_detail_report_output_directory(self):
"""Testing fail because output directory."""
with self.assertRaises(SystemExit):
with pytest.raises(SystemExit):
sys.argv = ["/bin/qpc", "report", "detail", "--json", "--output-file", "/"]
CLI().main()

def test_detail_report_output_directory_not_exist(self):
"""Testing fail because output directory does not exist."""
with self.assertRaises(SystemExit):
with pytest.raises(SystemExit):
sys.argv = [
"/bin/qpc",
"report",
Expand All @@ -180,7 +181,7 @@ def test_detail_report_output_directory_not_exist(self):

def test_detail_report_output_file_empty(self):
"""Testing fail because output file empty."""
with self.assertRaises(SystemExit):
with pytest.raises(SystemExit):
sys.argv = ["/bin/qpc", "report", "detail", "--json", "--output-file", ""]
CLI().main()

Expand All @@ -201,12 +202,10 @@ def test_detail_report_scan_job_not_exist(self):
path=self.test_json_filename,
mask=False,
)
with self.assertRaises(SystemExit):
with pytest.raises(SystemExit):
with redirect_stdout(report_out):
self.command.main(args)
self.assertEqual(
report_out.getvalue(), messages.REPORT_SJ_DOES_NOT_EXIST
)
assert report_out.getvalue() == messages.REPORT_SJ_DOES_NOT_EXIST

def test_detail_report_invalid_scan_job(self):
"""Details report with scanjob but no report_id."""
Expand All @@ -225,15 +224,15 @@ def test_detail_report_invalid_scan_job(self):
path=self.test_json_filename,
mask=False,
)
with self.assertRaises(SystemExit):
with pytest.raises(SystemExit):
with redirect_stdout(report_out):
self.command.main(args)
self.assertEqual(
report_out.getvalue(), messages.REPORT_NO_DETAIL_REPORT_FOR_SJ
assert (
report_out.getvalue() == messages.REPORT_NO_DETAIL_REPORT_FOR_SJ
)

@patch("qpc.report.details.write_file")
def test_details_file_fails_to_write(self, file):
def test_details_file_fails_to_write(self, file, caplog):
"""Testing details failure while writing to file."""
file.side_effect = EnvironmentError()
get_report_url = get_server_location() + REPORT_URI + "1/details/"
Expand All @@ -256,16 +255,16 @@ def test_details_file_fails_to_write(self, file):
path=self.test_json_filename,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.WRITE_FILE_ERROR % {
"path": self.test_json_filename,
"error": "",
}
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_details_nonexistent_directory(self):
def test_details_nonexistent_directory(self, caplog):
"""Testing error for nonexistent directory in output."""
fake_dir = "/cody/is/awesome/details.json"
get_report_url = get_server_location() + REPORT_URI + "1/details/"
Expand All @@ -283,15 +282,15 @@ def test_details_nonexistent_directory(self):
path=fake_dir,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.REPORT_DIRECTORY_DOES_NOT_EXIST % os.path.dirname(
fake_dir
)
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_details_nonjson_path(self):
def test_details_nonjson_path(self, caplog):
"""Testing error for non json file path."""
non_json_dir = "/Users/details.tar.gz"
get_report_url = get_server_location() + REPORT_URI + "1/details/"
Expand All @@ -309,13 +308,13 @@ def test_details_nonjson_path(self):
path=non_json_dir,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.OUTPUT_FILE_TYPE % ".json"
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_details_noncsv_path(self):
def test_details_noncsv_path(self, caplog):
"""Testing error for noncsv file path."""
non_csv_dir = "/Users/details.tar.gz"
get_report_url = get_server_location() + REPORT_URI + "1/details/"
Expand All @@ -333,13 +332,13 @@ def test_details_noncsv_path(self):
path=non_csv_dir,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.OUTPUT_FILE_TYPE % ".csv"
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_details_report_id_not_exist(self):
def test_details_report_id_not_exist(self, caplog):
"""Test details with nonexistent report id."""
get_report_url = get_server_location() + REPORT_URI + "1/details/"
get_report_json_data = {"id": 1, "report": [{"key": "value"}]}
Expand All @@ -359,13 +358,13 @@ def test_details_report_id_not_exist(self):
path=self.test_json_filename,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.REPORT_NO_DETAIL_REPORT_FOR_REPORT_ID % 1
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_detail_report_error_scan_job(self):
def test_detail_report_error_scan_job(self, caplog):
"""Testing error with scan job id."""
get_scanjob_url = get_server_location() + SCAN_JOB_URI + "1"
get_scanjob_json_data = {"id": 1, "report_id": 1}
Expand All @@ -390,13 +389,13 @@ def test_detail_report_error_scan_job(self):
path=self.test_json_filename,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.REPORT_NO_DETAIL_REPORT_FOR_SJ % 1
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text

def test_detail_report_as_csv_masked(self):
def test_detail_report_as_csv_masked(self, caplog):
"""Testing retrieving csv details report with masked query param."""
get_scanjob_url = get_server_location() + SCAN_JOB_URI + "1"
get_scanjob_json_data = {"id": 1, "report_id": 1}
Expand Down Expand Up @@ -426,15 +425,15 @@ def test_detail_report_as_csv_masked(self):
path=self.test_csv_filename,
mask=True,
)
with self.assertLogs(level="INFO") as log:
with caplog.at_level(logging.INFO):
self.command.main(args)
self.assertIn(messages.REPORT_SUCCESSFULLY_WRITTEN, log.output[-1])
assert messages.REPORT_SUCCESSFULLY_WRITTEN in caplog.text
with open(self.test_csv_filename, "r", encoding="utf-8") as json_file:
data = json_file.read()
file_content_dict = json.loads(data)
self.assertDictEqual(get_report_csv_data, file_content_dict)
assert get_report_csv_data == file_content_dict

def test_details_old_version(self):
def test_details_old_version(self, caplog):
"""Test too old server version."""
get_report_url = get_server_location() + REPORT_URI + "1/details/"
get_report_json_data = {"id": 1, "report": [{"key": "value"}]}
Expand All @@ -454,14 +453,14 @@ def test_details_old_version(self):
path=self.test_csv_filename,
mask=False,
)
with self.assertLogs(level="ERROR") as log:
with self.assertRaises(SystemExit):
with caplog.at_level(logging.ERROR):
with pytest.raises(SystemExit):
self.command.main(args)
err_msg = messages.SERVER_TOO_OLD_FOR_CLI % {
"min_version": "0.9.2",
"current_version": "0.0.45",
}
self.assertIn(err_msg, log.output[0])
assert err_msg in caplog.text


def test_details_report_as_json_no_output_file(caplog, capsys, requests_mock):
Expand Down
Loading
Loading