07.04 — Scénarios Corsicamon#
La page « Pokédex corse (Corsicadex) » de l’Igoristan. Saisie d’API key, tirage au sort avec 1/5 d’échec,
transient_errorspourError('lol'), et retries internes au POM face aux états « Corsicamons chargés / erreur réseau ».
Campagne#
# src/tests/campaigns/corsicamon.py
def create_igoristan_corsicamon_campaign(*, drivers_pool) -> TestCampaign:
return TestCampaign(
name="Corsicamon",
suites=[
create_corsicamon_happy_paths_test_suite(drivers_pool=drivers_pool),
create_corsicamon_unhappy_paths_test_suite(drivers_pool=drivers_pool),
],
)
def create_igoristan_corsicamon_smoke_campaign(*, drivers_pool) -> TestCampaign:
return TestCampaign(
name="Corsicamon - Smoke",
suites=[create_corsicamon_smoke_tests_suite(drivers_pool=drivers_pool)],
)Smoke test#
# tests/scenarios/corsicamon/enter_api_key.py
def scenario_enter_api_key_smoke(driver, logger):
page = CorsicamonEnterApiKeyPage(driver=driver)
...
return [
drive_page(
act(page, open_corsicamon_page)...,
act(page, verify_enter_api_key_screen)...,
),
]
test_enter_api_key_smoke = create_selenium_test(
name="Corsicamon - Smoke - enter API key screen visible",
test_scenario=lambda driver, logger: Scenario(
test_chain=scenario_enter_api_key_smoke(driver, logger)
),
)Vérifie juste que la page d’entrée d’API key s’affiche. Si elle ne s’affiche pas → smoke fail → main campaigns skippées.
Happy path : entrée API key + draw + add#
# tests/scenarios/corsicamon/new_draw.py
def scenario_new_draw_happy_path(driver, logger):
on_enter_key = CorsicamonEnterApiKeyPage(driver=driver)
on_main = CorsicamonMainPage(driver=driver)
env = create_env_getters()
api_key = env.get_value("igor_api_key")
return [
drive_page(
act(on_enter_key, open_corsicamon_page)...,
act(on_enter_key, enter_api_key_with_retries(api_key, retries=10, logger=logger))...,
act(on_enter_key, click_validate_api_key)...,
),
drive_page(
act(on_main, verify_main_page)...,
act(on_main, wait_for_pokemons_or_error_with_retries(retries=10, logger=logger))...,
act(on_main, verify_pokemons_displayed)...,
),
drive_page(
act(on_main, click_redraw_button)...,
act(on_main, wait_for_pokemons_or_error_with_retries(...))...,
act(on_main, verify_pokemons_displayed)...,
),
]- Open + enter API key + validate.
- Wait for corsicamons (avec retries pour le 1/5 d’échec).
- Re-draw avec retries.
Gestion du 1/5 d’échec#
corsicamon_main.py :
def wait_for_pokemons_or_error_with_retries(retries: int, logger: ILogger):
def unwrapped(p: CorsicamonMainPage) -> CorsicamonMainPage:
return p.wait_for_pokemons_or_error_with_retries(retries=retries, logger=logger)
return unwrappedpages/corsicamon/main.py :
def wait_for_pokemons_or_error_with_retries(self, *, retries: int, logger: ILogger) -> CorsicamonMainPage:
attempts = 1
while attempts <= retries:
try:
WebDriverWait(self._driver, get_timeout()).until(
lambda d: self._has_pokemons() or self._has_error()
)
break
except TimeoutException:
pass
if self._has_error():
logger.warning(f"Got error on attempt {attempts}/{retries}, retrying...")
self._click_redraw_button()
attempts += 1
continue
if self._has_pokemons():
return self
logger.info(f"Pokemons loaded after {attempts} attempts.")
return selfRetry interne au POM. Le scénario externe ne voit que « ça marche ou ça marche pas ».
Le choix « retry interne au POM » est documenté dans le CLAUDE.md du projet IA :
introduce-pom-retries— retries internes aux POMs, avec dédoublement (first-try + with-retries).
Unhappy paths#
tests/scenarios/corsicamon/…
- Entrée d’une API key invalide → vérifier le message d’erreur.
- …
Back to Igoristan#
# tests/scenarios/corsicamon/back_to_igoristan.py
def scenario_back_to_igoristan(driver, logger):
page = CorsicamonEnterApiKeyPage(driver=driver)
return [
drive_page(
act(page, open_corsicamon_page)...,
act(page, click_back_to_igoristan)...,
),
]
test_back_to_igoristan = create_selenium_test(
name="Corsicamon - Back to Igoristan",
test_scenario=lambda driver, logger: Scenario(test_chain=scenario_back_to_igoristan(driver, logger)),
post_test_scenarios_fragments=[verify_homepage],
)