120 lines
4.0 KiB
Python
120 lines
4.0 KiB
Python
"""Tests of the lecture script. A fake driver stands in for Chrome, so no browser starts."""
|
|
|
|
import pytest
|
|
from selenium import webdriver
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from scraping_wiki import interaction
|
|
from scraping_wiki.constants import (
|
|
ARTICLE_COUNT_SELECTOR,
|
|
CHROME_BINARY_ENV,
|
|
CHROMEDRIVER_PATH_ENV,
|
|
HEADLESS_ARGUMENT,
|
|
WIKIPEDIA_MAIN_PAGE_URL,
|
|
)
|
|
|
|
|
|
class FakeElement:
|
|
def __init__(self, text: str) -> None:
|
|
self.text = text
|
|
|
|
|
|
class FakeDriver:
|
|
def __init__(self, count: str = "7,123,456") -> None:
|
|
self.count = count
|
|
self.visited: list[str] = []
|
|
self.searched: list[tuple[str, str]] = []
|
|
self.is_quit = False
|
|
|
|
def get(self, url: str) -> None:
|
|
self.visited.append(url)
|
|
|
|
def find_element(self, by: str, value: str) -> FakeElement:
|
|
self.searched.append((by, value))
|
|
return FakeElement(self.count)
|
|
|
|
def quit(self) -> None:
|
|
self.is_quit = True
|
|
|
|
|
|
class RecordingChrome:
|
|
def __init__(self, options: object, service: object) -> None:
|
|
self.options = options
|
|
self.service = service
|
|
|
|
|
|
def test_open_main_page_gets_the_wikipedia_url() -> None:
|
|
driver = FakeDriver()
|
|
interaction.open_main_page(driver) # type: ignore[arg-type]
|
|
assert driver.visited == [WIKIPEDIA_MAIN_PAGE_URL]
|
|
|
|
|
|
def test_read_article_count_uses_the_css_selector_and_returns_the_text() -> None:
|
|
driver = FakeDriver("7,000,001")
|
|
assert interaction.read_article_count(driver) == "7,000,001" # type: ignore[arg-type]
|
|
assert driver.searched == [(By.CSS_SELECTOR, ARTICLE_COUNT_SELECTOR)]
|
|
|
|
|
|
def test_main_prints_the_count_and_quits_the_driver(
|
|
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
driver = FakeDriver("6,999,999")
|
|
monkeypatch.setattr(interaction, "create_driver", lambda headless=False: driver)
|
|
assert interaction.main([]) == 0
|
|
assert capsys.readouterr().out == "6,999,999\n"
|
|
assert driver.visited == [WIKIPEDIA_MAIN_PAGE_URL]
|
|
assert driver.is_quit
|
|
|
|
|
|
def test_main_quits_the_driver_when_reading_fails(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
driver = FakeDriver()
|
|
|
|
def fail(_driver: object) -> str:
|
|
raise RuntimeError("element not found")
|
|
|
|
monkeypatch.setattr(interaction, "create_driver", lambda headless=False: driver)
|
|
monkeypatch.setattr(interaction, "read_article_count", fail)
|
|
with pytest.raises(RuntimeError):
|
|
interaction.main([])
|
|
assert driver.is_quit
|
|
|
|
|
|
def test_main_passes_the_headless_flag_to_create_driver(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
seen: list[bool] = []
|
|
|
|
def fake_create(headless: bool = False) -> FakeDriver:
|
|
seen.append(headless)
|
|
return FakeDriver()
|
|
|
|
monkeypatch.setattr(interaction, "create_driver", fake_create)
|
|
interaction.main(["--headless"])
|
|
interaction.main([])
|
|
assert seen == [True, False]
|
|
|
|
|
|
def test_create_driver_adds_the_headless_options_only_when_asked(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
monkeypatch.delenv(CHROME_BINARY_ENV, raising=False)
|
|
monkeypatch.delenv(CHROMEDRIVER_PATH_ENV, raising=False)
|
|
monkeypatch.setattr(
|
|
webdriver, "Chrome", lambda options, service: RecordingChrome(options, service)
|
|
)
|
|
plain = interaction.create_driver()
|
|
headless = interaction.create_driver(headless=True)
|
|
assert HEADLESS_ARGUMENT not in plain.options.arguments # type: ignore[attr-defined]
|
|
assert HEADLESS_ARGUMENT in headless.options.arguments # type: ignore[attr-defined]
|
|
|
|
|
|
def test_create_driver_uses_the_binaries_named_in_the_environment(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
monkeypatch.setenv(CHROME_BINARY_ENV, "/usr/bin/chromium")
|
|
monkeypatch.setenv(CHROMEDRIVER_PATH_ENV, "/usr/bin/chromedriver")
|
|
monkeypatch.setattr(
|
|
webdriver, "Chrome", lambda options, service: RecordingChrome(options, service)
|
|
)
|
|
driver = interaction.create_driver()
|
|
assert driver.options.binary_location == "/usr/bin/chromium" # type: ignore[attr-defined]
|
|
assert driver.service.path == "/usr/bin/chromedriver" # type: ignore[attr-defined]
|