|
1 | 1 | """Integration tests for the public API functionality.""" |
2 | 2 |
|
| 3 | +from __future__ import annotations |
| 4 | + |
| 5 | +from typing import TYPE_CHECKING |
| 6 | + |
3 | 7 | import pytest |
4 | 8 |
|
5 | 9 | import language_tool_python |
6 | 10 | from language_tool_python.exceptions import RateLimitError |
7 | 11 |
|
| 12 | +if TYPE_CHECKING: |
| 13 | + from language_tool_python.match import Match |
| 14 | + |
| 15 | +_ES_TEXT = ( |
| 16 | + "Escriba un texto aquí. LanguageTool le ayudará a afrentar " |
| 17 | + "algunas dificultades propias de la escritura. Se a hecho un esfuerzo " |
| 18 | + "para detectar errores tipográficos, ortograficos y incluso " |
| 19 | + "gramaticales. También algunos errores de estilo, a grosso modo." |
| 20 | +) |
8 | 21 |
|
9 | | -def test_remote_es() -> None: |
10 | | - """Test the public API with Spanish language text. |
11 | 22 |
|
12 | | - This test verifies that the LanguageToolPublicAPI correctly identifies various |
13 | | - errors in a Spanish text sample. |
| 23 | +@pytest.fixture(scope="module") |
| 24 | +def es_matches() -> list[Match]: |
| 25 | + """Check ``_ES_TEXT`` once against the public API and share the result. |
14 | 26 |
|
15 | | - :raises AssertionError: If the detected matches do not match the expected output. |
| 27 | + The check is only performed once (module-scoped) to limit the number of |
| 28 | + requests sent to the public API. If the request is rate-limited, every test |
| 29 | + depending on this fixture is skipped silently rather than failing. |
16 | 30 | """ |
17 | 31 | try: |
18 | 32 | with language_tool_python.LanguageToolPublicAPI("es") as tool: |
19 | | - es_text = ( |
20 | | - "Escriba un texto aquí. LanguageTool le ayudará a afrentar " |
21 | | - "algunas dificultades propias de la escritura. Se a hecho un esfuerzo " |
22 | | - "para detectar errores tipográficos, ortograficos y incluso " |
23 | | - "gramaticales. También algunos errores de estilo, a grosso modo." |
24 | | - ) |
25 | | - matches = tool.check(es_text) |
26 | | - assert ( |
27 | | - str(matches) |
28 | | - == """[Match({'rule_id': 'AFRENTAR_DIFICULTADES', 'message': 'Confusión |
29 | | - entre «afrontar» y «afrentar».', 'replacements': ['afrontar'], |
30 | | - 'offset_in_context': 43, 'context': '...n texto aquí. |
31 | | -
|
32 | | - LanguageTool le ayudará a afrentar algunas dificultades propias de la |
33 | | - escr...', 'offset': 49, 'error_length': 8, 'category': |
34 | | - 'INCORRECT_EXPRESSIONS', 'rule_issue_type': 'grammar', 'sentence': |
35 | | - 'LanguageTool le ayudará a afrentar algunas dificultades propias de |
36 | | - la escritura.'}), Match({'rule_id': 'PRON_HABER_PARTICIPIO', |
37 | | - 'message': 'El v. ‘haber’ se escribe con hache.', |
38 | | - 'replacements': ['ha'], 'offset_in_context': 43, 'context': |
39 | | - '...ificultades propias de la escritura. Se a hecho un esfuerzo para |
40 | | - detectar errores...', 'offset': 107, 'error_length': 1, 'category': |
41 | | - 'MISSPELLING', 'rule_issue_type': 'misspelling', 'sentence': 'Se a |
42 | | - hecho un esfuerzo para detectar errores tipográficos, ortograficos y |
43 | | - incluso gramaticales.'}), Match({'rule_id': 'MORFOLOGIK_RULE_ES', |
44 | | - 'message': 'Se ha encontrado un posible error ortográfico.', |
45 | | - 'replacements': ['ortográficos', 'ortográficas', 'ortográfico', |
46 | | - 'orográficos', 'ortografiaos', 'ortografíeos'], 'offset_in_context': |
47 | | - 43, 'context': '...rzo para detectar errores tipográficos, |
48 | | - ortograficos y incluso gramaticales. También algunos...', 'offset': |
49 | | - 163, 'error_length': 12, 'category': 'TYPOS', 'rule_issue_type': |
50 | | - 'misspelling', 'sentence': 'Se a hecho un esfuerzo para detectar |
51 | | - errores tipográficos, ortograficos y incluso gramaticales.'}), |
52 | | - Match({'rule_id': 'Y_E_O_U', 'message': 'Cuando precede a palabras |
53 | | - que comienzan por ‘i’, la conjunción ‘y’ se |
54 | | - transforma en ‘e’.', 'replacements': ['e'], |
55 | | - 'offset_in_context': 43, 'context': '...ctar errores tipográficos, |
56 | | - ortograficos y incluso gramaticales. También algunos e...', 'offset': |
57 | | - 176, 'error_length': 1, 'category': 'GRAMMAR', 'rule_issue_type': |
58 | | - 'grammar', 'sentence': 'Se a hecho un esfuerzo para detectar errores |
59 | | - tipográficos, ortograficos y incluso gramaticales.'}), |
60 | | - Match({'rule_id': 'GROSSO_MODO', 'message': 'Esta expresión latina se |
61 | | - usa sin preposición.', 'replacements': ['grosso modo'], |
62 | | - 'offset_in_context': 43, 'context': '...les. También algunos errores |
63 | | - de estilo, a grosso modo.', 'offset': 235, 'error_length': 13, |
64 | | - 'category': 'GRAMMAR', 'rule_issue_type': 'grammar', 'sentence': |
65 | | - 'También algunos errores de estilo, a grosso modo.'})] |
66 | | - """ |
67 | | - ) |
| 33 | + return tool.check(_ES_TEXT) |
68 | 34 | except RateLimitError: |
69 | 35 | pytest.skip("Rate limit exceeded for public API.") |
| 36 | + |
| 37 | + |
| 38 | +@pytest.mark.parametrize( |
| 39 | + ("rule_id", "category", "offset"), |
| 40 | + [ |
| 41 | + ("AFRENTAR_DIFICULTADES", "INCORRECT_EXPRESSIONS", 49), |
| 42 | + ("PRON_HABER_PARTICIPIO", "MISSPELLING", 107), |
| 43 | + ("MORFOLOGIK_RULE_ES", "TYPOS", 163), |
| 44 | + ("Y_E_O_U", "GRAMMAR", 176), |
| 45 | + ("GROSSO_MODO", "GRAMMAR", 235), |
| 46 | + ], |
| 47 | +) |
| 48 | +def test_remote_es( |
| 49 | + es_matches: list[Match], |
| 50 | + rule_id: str, |
| 51 | + category: str, |
| 52 | + offset: int, |
| 53 | +) -> None: |
| 54 | + """Test that the public API detects a specific known error in Spanish text. |
| 55 | +
|
| 56 | + LanguageTool rules can change over time, so this asserts on individual match |
| 57 | + fields (rule_id, category, offset) rather than requiring the entire response |
| 58 | + to match a frozen snapshot exactly. |
| 59 | +
|
| 60 | + :raises AssertionError: If no match with the expected fields is found. |
| 61 | + """ |
| 62 | + assert any( |
| 63 | + m.rule_id == rule_id and m.category == category and m.offset == offset |
| 64 | + for m in es_matches |
| 65 | + ) |
0 commit comments