Implemented tests for CapturingTask. A few mock classes where needed.
This commit is contained in:
parent
007f458cd5
commit
cf4ce06b57
3 changed files with 267 additions and 236 deletions
170
tests/capturer_test.py
Normal file
170
tests/capturer_test.py
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
from tests.mock_classes import (
|
||||||
|
MockCapturingInterface,
|
||||||
|
MockParsingFlow,
|
||||||
|
MockUrlAttackReturnsSuccess,
|
||||||
|
MockUrlAttackReturnsFailure,
|
||||||
|
)
|
||||||
|
from capturer.capturer import CapturingTask
|
||||||
|
|
||||||
|
|
||||||
|
def test_capturing_task_successful_task_flow():
|
||||||
|
|
||||||
|
the_task_parameters = dict()
|
||||||
|
the_task_parameters["uuid"] = "test_uuid"
|
||||||
|
the_task_parameters["ad_url"] = "test_url"
|
||||||
|
the_task_parameters["fk_uuid_exploring"] = "test_exploring_uuid"
|
||||||
|
the_task_parameters["status"] = "Pending"
|
||||||
|
|
||||||
|
fake_resulting_field_values = {
|
||||||
|
"a_field": {"a_value": 1},
|
||||||
|
"another_field": {"another_value": 2},
|
||||||
|
}
|
||||||
|
mock_parsing_flow = MockParsingFlow(
|
||||||
|
mock_all_found_fields_are_valid=True,
|
||||||
|
mock_all_non_optional_fields_were_found=True,
|
||||||
|
mock_field_values_to_return=fake_resulting_field_values,
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_capturing_interface = MockCapturingInterface()
|
||||||
|
|
||||||
|
task = CapturingTask(
|
||||||
|
task_parameters=the_task_parameters,
|
||||||
|
capturing_interface=mock_capturing_interface,
|
||||||
|
new_parsing_flow=mock_parsing_flow,
|
||||||
|
url_acquisition_object=MockUrlAttackReturnsSuccess,
|
||||||
|
dead_ad_checker=lambda: False,
|
||||||
|
)
|
||||||
|
|
||||||
|
task.capture()
|
||||||
|
|
||||||
|
final_data = task.get_ad_data()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(mock_capturing_interface.tasks) == 1
|
||||||
|
and mock_capturing_interface.tasks[the_task_parameters["uuid"]][-1].status
|
||||||
|
== "Data ready"
|
||||||
|
and fake_resulting_field_values == final_data
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_capturing_task_dead_ad_task_flow():
|
||||||
|
the_task_parameters = dict()
|
||||||
|
the_task_parameters["uuid"] = "test_uuid"
|
||||||
|
the_task_parameters["ad_url"] = "test_url"
|
||||||
|
the_task_parameters["fk_uuid_exploring"] = "test_exploring_uuid"
|
||||||
|
the_task_parameters["status"] = "Pending"
|
||||||
|
|
||||||
|
mock_parsing_flow = MockParsingFlow(
|
||||||
|
mock_all_found_fields_are_valid=False,
|
||||||
|
issues_to_return={"some_field": {"valid": False}},
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_capturing_interface = MockCapturingInterface()
|
||||||
|
|
||||||
|
task = CapturingTask(
|
||||||
|
task_parameters=the_task_parameters,
|
||||||
|
capturing_interface=mock_capturing_interface,
|
||||||
|
new_parsing_flow=mock_parsing_flow,
|
||||||
|
url_acquisition_object=MockUrlAttackReturnsFailure,
|
||||||
|
dead_ad_checker=lambda x: True,
|
||||||
|
)
|
||||||
|
|
||||||
|
task.capture()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(mock_capturing_interface.tasks) == 1
|
||||||
|
and mock_capturing_interface.tasks[the_task_parameters["uuid"]][-1].status
|
||||||
|
== "Dead ad"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_capturing_task_invalid_fields_surrender_flow():
|
||||||
|
the_task_parameters = dict()
|
||||||
|
the_task_parameters["uuid"] = "test_uuid"
|
||||||
|
the_task_parameters["ad_url"] = "test_url"
|
||||||
|
the_task_parameters["fk_uuid_exploring"] = "test_exploring_uuid"
|
||||||
|
the_task_parameters["status"] = "Pending"
|
||||||
|
|
||||||
|
mock_parsing_flow = MockParsingFlow(
|
||||||
|
mock_all_found_fields_are_valid=False,
|
||||||
|
issues_to_return={"some_field": {"valid": False}},
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_capturing_interface = MockCapturingInterface()
|
||||||
|
|
||||||
|
task = CapturingTask(
|
||||||
|
task_parameters=the_task_parameters,
|
||||||
|
capturing_interface=mock_capturing_interface,
|
||||||
|
new_parsing_flow=mock_parsing_flow,
|
||||||
|
url_acquisition_object=MockUrlAttackReturnsSuccess,
|
||||||
|
dead_ad_checker=lambda: False,
|
||||||
|
)
|
||||||
|
|
||||||
|
task.capture()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(mock_capturing_interface.tasks) == 1
|
||||||
|
and mock_capturing_interface.tasks[the_task_parameters["uuid"]][-1].status
|
||||||
|
== "Invalid value fields"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_capturing_task_missing_fields_surrender_flow():
|
||||||
|
the_task_parameters = dict()
|
||||||
|
the_task_parameters["uuid"] = "test_uuid"
|
||||||
|
the_task_parameters["ad_url"] = "test_url"
|
||||||
|
the_task_parameters["fk_uuid_exploring"] = "test_exploring_uuid"
|
||||||
|
the_task_parameters["status"] = "Pending"
|
||||||
|
|
||||||
|
mock_parsing_flow = MockParsingFlow(
|
||||||
|
mock_all_non_optional_fields_were_found=False,
|
||||||
|
issues_to_return={"some_field": {"found": False}},
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_capturing_interface = MockCapturingInterface()
|
||||||
|
|
||||||
|
task = CapturingTask(
|
||||||
|
task_parameters=the_task_parameters,
|
||||||
|
capturing_interface=mock_capturing_interface,
|
||||||
|
new_parsing_flow=mock_parsing_flow,
|
||||||
|
url_acquisition_object=MockUrlAttackReturnsSuccess,
|
||||||
|
dead_ad_checker=lambda: False,
|
||||||
|
)
|
||||||
|
|
||||||
|
task.capture()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(mock_capturing_interface.tasks) == 1
|
||||||
|
and mock_capturing_interface.tasks[the_task_parameters["uuid"]][-1].status
|
||||||
|
== "Fields missing"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_capturing_task_unexpected_issue_surrender_flow():
|
||||||
|
the_task_parameters = dict()
|
||||||
|
the_task_parameters["uuid"] = "test_uuid"
|
||||||
|
the_task_parameters["ad_url"] = "test_url"
|
||||||
|
the_task_parameters["fk_uuid_exploring"] = "test_exploring_uuid"
|
||||||
|
the_task_parameters["status"] = "Pending"
|
||||||
|
|
||||||
|
mock_parsing_flow = MockParsingFlow()
|
||||||
|
|
||||||
|
mock_capturing_interface = MockCapturingInterface()
|
||||||
|
|
||||||
|
CapturingTask.sleep_time_failed_request = 0 # Override quite long sleep time
|
||||||
|
|
||||||
|
task = CapturingTask(
|
||||||
|
task_parameters=the_task_parameters,
|
||||||
|
capturing_interface=mock_capturing_interface,
|
||||||
|
new_parsing_flow=mock_parsing_flow,
|
||||||
|
url_acquisition_object=MockUrlAttackReturnsFailure,
|
||||||
|
dead_ad_checker=lambda x: False,
|
||||||
|
)
|
||||||
|
|
||||||
|
task.capture()
|
||||||
|
|
||||||
|
assert (
|
||||||
|
len(mock_capturing_interface.tasks) == 1
|
||||||
|
and mock_capturing_interface.tasks[the_task_parameters["uuid"]][-1].status
|
||||||
|
== "Surrender"
|
||||||
|
)
|
||||||
File diff suppressed because one or more lines are too long
97
tests/mock_classes.py
Normal file
97
tests/mock_classes.py
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
from collections import namedtuple
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from db_layer.capturing_tasks_interface import CapturingTasksInterface
|
||||||
|
from core.parsing_utils import ParsingFlow
|
||||||
|
from core.scrapping_utils import UrlAttack
|
||||||
|
|
||||||
|
|
||||||
|
class MockCapturingInterface(CapturingTasksInterface):
|
||||||
|
|
||||||
|
task_state_record = namedtuple(
|
||||||
|
"TaskStateRecord", ["uuid", "uuid_exploring", "status", "ad_url"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.tasks = {}
|
||||||
|
|
||||||
|
def update_capturing_task(self, uuid, uuid_exploring, status, ad_url):
|
||||||
|
if uuid not in self.tasks:
|
||||||
|
self.tasks[uuid] = []
|
||||||
|
|
||||||
|
self.tasks[uuid].append(
|
||||||
|
MockCapturingInterface.task_state_record(
|
||||||
|
uuid=uuid, uuid_exploring=uuid_exploring, status=status, ad_url=ad_url
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MockParsingFlow(ParsingFlow):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
issues_to_return: Dict[str, dict] = None,
|
||||||
|
mock_all_found_fields_are_valid: bool = True,
|
||||||
|
mock_all_non_optional_fields_were_found: bool = True,
|
||||||
|
mock_field_values_to_return: Dict[str, dict] = None,
|
||||||
|
):
|
||||||
|
args_with_empty_dict_as_default = [
|
||||||
|
issues_to_return,
|
||||||
|
mock_field_values_to_return,
|
||||||
|
]
|
||||||
|
for arg in args_with_empty_dict_as_default:
|
||||||
|
if arg is None:
|
||||||
|
arg = dict()
|
||||||
|
|
||||||
|
self._issues = issues_to_return
|
||||||
|
self._mock_all_found_fields_are_valid = mock_all_found_fields_are_valid
|
||||||
|
self._mock_field_values_to_return = mock_field_values_to_return
|
||||||
|
self._mock_all_non_optional_fields_were_found = (
|
||||||
|
mock_all_non_optional_fields_were_found
|
||||||
|
)
|
||||||
|
|
||||||
|
def execute_flow(self, soup: BeautifulSoup) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issues(self) -> Dict[str, dict]:
|
||||||
|
return self._issues
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_found_fields_are_valid(self) -> bool:
|
||||||
|
return self._mock_all_found_fields_are_valid
|
||||||
|
|
||||||
|
@property
|
||||||
|
def all_non_optional_fields_were_found(self) -> bool:
|
||||||
|
return self._mock_all_non_optional_fields_were_found
|
||||||
|
|
||||||
|
@property
|
||||||
|
def field_values(self) -> Dict:
|
||||||
|
return self._mock_field_values_to_return
|
||||||
|
|
||||||
|
|
||||||
|
class MockUrlAttack(UrlAttack):
|
||||||
|
def __init__(self, url: str) -> None:
|
||||||
|
super().__init__(url=url)
|
||||||
|
|
||||||
|
def get_text(self) -> str:
|
||||||
|
return "<html>this_is_a_fake_html_string</html>"
|
||||||
|
|
||||||
|
|
||||||
|
class MockUrlAttackReturnsSuccess(MockUrlAttack):
|
||||||
|
def __init__(self, url: str) -> None:
|
||||||
|
super().__init__(url=url)
|
||||||
|
|
||||||
|
def attack(self) -> None:
|
||||||
|
self.success = True
|
||||||
|
self.has_been_attacked = True
|
||||||
|
|
||||||
|
|
||||||
|
class MockUrlAttackReturnsFailure(MockUrlAttack):
|
||||||
|
def __init__(self, url: str) -> None:
|
||||||
|
super().__init__(url=url)
|
||||||
|
|
||||||
|
def attack(self) -> None:
|
||||||
|
self.success = False
|
||||||
|
self.has_been_attacked = True
|
||||||
Loading…
Add table
Add a link
Reference in a new issue