Spaces:
Running
Running
File size: 3,136 Bytes
232eb80 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | """The search URLs each scraper navigates to.
These had no coverage at all, and the gap was invisible: the Playwright
tests drive a real browser but patch `page.goto` with a stand-in that
accepts the URL and discards it, so everything downstream of navigation
was verified and everything upstream was not. Mutation testing confirmed
it - replacing the Bing URL with a constant, dropping `&num=` from the
Scholar URL, and making the Google Patents URL ignore the query all left
the full suite green. A scraper that searched for the wrong thing entirely
passed.
These are pure string assertions: no browser, no fixtures, microseconds.
"""
import pytest
from serp import (
bing_search_url,
brave_search_url,
google_patents_search_url,
google_scholar_url,
)
class TestQueryIsIncluded:
"""The single most important property: the URL must ask for what the
caller asked for."""
@pytest.mark.parametrize("builder", [
bing_search_url, brave_search_url, google_patents_search_url, google_scholar_url])
def test_the_query_reaches_the_url(self, builder):
assert "widgets" in builder("widgets", 10)
@pytest.mark.parametrize("builder", [
bing_search_url, brave_search_url, google_patents_search_url, google_scholar_url])
def test_a_different_query_produces_a_different_url(self, builder):
assert builder("widgets", 10) != builder("gadgets", 10)
class TestQueryIsEncoded:
"""A raw query in a URL is both a correctness bug (spaces, ampersands
and hashes truncate or corrupt the search) and the kind of thing that
turns user input into URL structure."""
@pytest.mark.parametrize("builder", [
bing_search_url, brave_search_url, google_patents_search_url, google_scholar_url])
def test_spaces_are_encoded(self, builder):
url = builder("agentic ai", 10)
assert "agentic+ai" in url or "agentic%20ai" in url
assert "agentic ai" not in url
@pytest.mark.parametrize("builder", [
bing_search_url, brave_search_url, google_patents_search_url, google_scholar_url])
def test_url_significant_characters_are_escaped(self, builder):
url = builder("a&b=c#d", 10)
query_part = url.split("?", 1)[1]
# Exactly one separator per parameter the builder itself added.
assert "a&b=c#d" not in query_part
assert "%26" in query_part
class TestResultCount:
def test_scholar_asks_for_the_requested_number_of_results(self):
assert "num=25" in google_scholar_url("widgets", 25)
def test_google_patents_asks_for_the_requested_number_of_results(self):
assert "num=25" in google_patents_search_url("widgets", 25)
class TestHosts:
@pytest.mark.parametrize("builder, host", [
(bing_search_url, "https://www.bing.com/search"),
(brave_search_url, "https://search.brave.com/search"),
(google_patents_search_url, "https://patents.google.com/"),
(google_scholar_url, "https://scholar.google.com/scholar"),
])
def test_points_at_the_expected_endpoint(self, builder, host):
assert builder("widgets", 10).startswith(host)
|