Skip to content

Commit

Permalink
fix: more unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
robbrad committed Sep 5, 2024
1 parent b831213 commit 23c65ae
Showing 1 changed file with 197 additions and 0 deletions.
197 changes: 197 additions & 0 deletions uk_bin_collection/tests/test_get_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import os
from unittest import mock
import tempfile

import pytest
from requests import exceptions as req_exp
from requests.models import Response
from unittest.mock import patch
from uk_bin_collection.get_bin_data import AbstractGetBinDataClass as agbdc
from uk_bin_collection.get_bin_data import setup_logging
import logging


def mocked_requests_get(*args, **kwargs):
class MockResponse:
def __init__(self, json_data, status_code, raise_error_type):
self.text = json_data
self.status_code = status_code
if raise_error_type is not None:
self.raise_for_status = self.raise_error(raise_error_type)
else:
self.raise_for_status = lambda: None

def raise_error(self, errorType):
if errorType == "HTTPError":
raise req_exp.HTTPError()
elif errorType == "ConnectionError":
raise req_exp.ConnectionError()
elif errorType == "Timeout":
raise req_exp.Timeout()
elif errorType == "RequestException":
raise req_exp.RequestException()
return errorType

if args[0] == "aurl":
return MockResponse({"test_data": "test"}, 200, None)
elif args[0] == "HTTPError":
return MockResponse({}, 999, "HTTPError")
elif args[0] == "ConnectionError":
return MockResponse({}, 999, "ConnectionError")
elif args[0] == "Timeout":
return MockResponse({}, 999, "Timeout")
elif args[0] == "RequestException":
return MockResponse({}, 999, "RequestException")
elif args[0] == "notPage":
return MockResponse("not json", 200, None)
return MockResponse(None, 404, "HTTPError")


# Unit tests


def test_logging_exception():
logging_dict = "SW1A 1AA"
with pytest.raises(ValueError) as exc_info:
result = setup_logging(logging_dict, "ROOT")
assert exc_info.typename == "ValueError"


def test_setup_logging_valid_config():
# Example of a minimal valid logging configuration dictionary
logging_config = {
"version": 1,
"handlers": {
"console": {
"class": "logging.StreamHandler",
"level": "DEBUG",
},
},
"loggers": {
"ROOT": {
"handlers": ["console"],
"level": "DEBUG",
},
},
}
logger_name = "ROOT"
# Run the function with valid logging configuration
logger = setup_logging(logging_config, logger_name)

# Assert that logger is correctly configured
assert logger.name == logger_name
assert logger.level == logging.DEBUG


@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_get_data(mock_get):
page_data = agbdc.get_data("aurl")
assert page_data.text == {"test_data": "test"}


@pytest.mark.parametrize(
"url", ["HTTPError", "ConnectionError", "Timeout", "RequestException"]
)
@mock.patch("requests.get", side_effect=mocked_requests_get)
def test_get_data_error(mock_get, url):
with pytest.raises(Exception) as exc_info:
result = agbdc.get_data(url)
assert exc_info.typename == url


def test_output_json():
bin_data = {"bin": ""}
output = agbdc.output_json(bin_data)
assert type(output) == str
assert output == '{\n "bin": ""\n}'

class ConcreteGetBinDataClass(agbdc):
"""Concrete implementation of the abstract class to test abstract methods."""
def parse_data(self, page: str, **kwargs) -> dict:
return {"mock_key": "mock_value"}

def update_dev_mode_data(self, council_module_str, this_url, **kwargs):
# You can implement the method or delegate it to the abstract class's method
super().update_dev_mode_data(council_module_str, this_url, **kwargs)

@pytest.fixture
def concrete_class_instance():
return ConcreteGetBinDataClass()

def test_get_and_parse_data_no_skip_get_url(concrete_class_instance):
mock_page = "mocked page content"
mock_parsed_data = {"mock_key": "mock_value"}

with mock.patch.object(concrete_class_instance, 'get_data', return_value=mock_page) as mock_get_data, \
mock.patch.object(concrete_class_instance, 'parse_data', return_value=mock_parsed_data) as mock_parse_data:

result = concrete_class_instance.get_and_parse_data("http://example.com")

mock_get_data.assert_called_once_with("http://example.com")
mock_parse_data.assert_called_once_with(mock_page, url="http://example.com")
assert result == mock_parsed_data

def test_get_and_parse_data_skip_get_url(concrete_class_instance):
mock_parsed_data = {"mock_key": "mock_value"}

with mock.patch.object(concrete_class_instance, 'parse_data', return_value=mock_parsed_data) as mock_parse_data:

result = concrete_class_instance.get_and_parse_data("http://example.com", skip_get_url=True)

mock_parse_data.assert_called_once_with("", url="http://example.com", skip_get_url=True)
assert result == mock_parsed_data

@pytest.fixture
def setup_test_update_dev_mode_data():
"""Fixture to set up and tear down the environment for test_update_dev_mode_data"""
# Create a temporary directory to simulate the working directory
test_dir = tempfile.TemporaryDirectory()

# Patch os.getcwd() to return the temporary directory
cwd_patch = patch('os.getcwd', return_value=test_dir.name)
mock_getcwd = cwd_patch.start()

# Ensure the nested directory structure exists
os.makedirs(os.path.join(test_dir.name, "uk_bin_collection", "tests"))

# Yield control back to the test, then clean up after the test
yield test_dir.name # Provide the test with the temporary directory

# Teardown
test_dir.cleanup()
cwd_patch.stop()


def test_update_dev_mode_data(setup_test_update_dev_mode_data):
"""Test update_dev_mode_data method to ensure input.json is updated correctly"""
# The setup fixture returns the mocked current working directory
mock_cwd = setup_test_update_dev_mode_data

# Create an instance of the concrete class that inherits from AbstractGetBinDataClass
obj = ConcreteGetBinDataClass()

# Define input arguments for the method
council_module_str = 'test_council_module'
this_url = 'https://example.com'
kwargs = {
'postcode': '12345',
'paon': '1A',
'uprn': '100012345',
'usrn': '200012345',
'web_driver': 'mocked_web_driver',
'skip_get_url': True,
}

# Call the method being tested on the instance
obj.update_dev_mode_data(council_module_str, this_url, **kwargs)

# Verify that input.json was created in the correct location
input_file_path = os.path.join(mock_cwd, "uk_bin_collection", "tests", "input.json")
assert os.path.exists(input_file_path)

# Read the contents of the file and make necessary assertions
with open(input_file_path, 'r') as f:
file_content = f.read()

# Example assertion - check if certain values exist in the file content (based on your actual file format)
assert '100012345' in file_content # Checking UPRN as an example

0 comments on commit 23c65ae

Please sign in to comment.