keepcalculator

06 Numbers and Powers

Selenium Test Failures in Pytest: Fix Guide

Card No. 06·55258 · Updated · Standard formula, shown below

This guide walks you through diagnosing and fixing Selenium test failures when running under pytest. You’ll learn the common causes, how to read the error output, and step-by-step fixes that get your tests green again.

What You’ll Need

  • A Python project with pytest and Selenium installed (pip install pytest selenium)
  • A web driver (ChromeDriver, GeckoDriver, etc.) matching your browser version
  • Basic familiarity with pytest fixtures and Selenium commands

Step-by-Step

  1. Reproduce the failure in isolation. Run only the failing test with pytest tests/test_login.py::test_valid_login -v. Note the exact error message and the line where it fails. This tells you whether it’s a setup issue, a locator problem, or a timing issue.
  2. Check the browser and driver versions. Selenium requires the driver to match the browser major version. Run chromedriver --version and compare with your Chrome version (chrome://settings/help). If they mismatch, download the correct driver or update your browser.
  3. Inspect the error type. Common Selenium exceptions:
    • NoSuchElementException – locator not found. Verify the element exists (maybe in an iframe or shadow DOM).
    • ElementNotInteractableException – element is present but hidden or covered. Wait for visibility/clickability.
    • TimeoutException – explicit wait expired. Increase the timeout or refine the expected condition.
    • WebDriverException – driver crashed or connection lost. Restart the driver and check for resource leaks.
  4. Add explicit waits instead of sleep. Replace time.sleep(2) with WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "submit"))). This makes tests robust to varying load times.
  5. Use pytest fixtures for setup and teardown. Create a conftest.py with a driver fixture that yields the WebDriver and quits it afterward. This prevents orphaned browser processes and ensures a clean state per test.
  6. Take a screenshot on failure. In your fixture, add a try/except that captures driver.save_screenshot('failure.png') when an assertion fails. This gives visual evidence of the page state at the moment of failure.
  7. Run with verbose logging. Use pytest --log-cli-level=DEBUG to see Selenium’s internal commands. This helps identify which action caused the failure.
  8. Isolate test independence. Ensure each test starts from a known state (e.g., a fresh session or a clean database). Tests that depend on order often fail when run in a different sequence.
  9. Check for cross-browser issues. If tests pass in one browser but fail in another, use browser-specific locators or adjust waits. Consider using a cloud grid for broader coverage.
  10. Review your locators. Prefer stable attributes like IDs over XPath that depends on page structure. Use data-testid attributes if your team controls the frontend.

Common Mistakes

  • Using absolute XPath that breaks with any layout change.
  • Forgetting to quit the driver, leading to too many open processes and resource exhaustion.
  • Relying on time.sleep() for synchronization – it’s brittle and slows down the suite.
  • Not handling iframes or shadow DOM – elements inside them are not directly accessible.
  • Running tests in parallel without ensuring each test has its own driver instance.

Tips

  • Use pytest-selenium plugin for built-in fixtures and screenshot support.
  • Set a global implicit wait (e.g., driver.implicitly_wait(5)) but use explicit waits for critical elements.
  • Structure your tests with Page Object Model to reduce duplication and make locators easier to update.
  • Run tests in headless mode locally to speed up debugging, but keep headed mode for final verification.
  • Use @pytest.mark.flaky(reruns=2) from pytest-rerunfailures to handle intermittent network issues, but investigate the root cause rather than masking it.

Troubleshooting

If the test still fails after the steps above:

  • Try a different browser. If Chrome fails, try Firefox. This isolates whether the issue is driver-specific.
  • Check for pop-ups or new tabs. Selenium doesn’t automatically switch to new windows. Use driver.switch_to.window(driver.window_handles[-1]).
  • Verify the test environment. Is the URL correct? Is the test server running? Check for VPN or proxy issues that might block requests.
  • Examine the page source. In the failure screenshot, view the HTML to see if the element is actually there but with a different attribute.
  • Check for JavaScript errors. Open the browser console manually (or via driver.get_log('browser')) to see if a script error is preventing the UI from rendering.
  • Run the test with --pdb. This drops you into the debugger at the failure point, letting you inspect the driver state interactively.

Frequently Asked Questions

Why does my test pass locally but fail in CI?

CI environments often have different screen resolutions, browser versions, or network speeds. Use explicit waits and ensure your driver is installed on the CI machine. Also, headless mode might behave differently – test with the same settings.

How do I handle dynamic elements that appear after an AJAX call?

Use WebDriverWait with EC.presence_of_element_located or visibility_of_element_located. This waits until the element is ready, regardless of how long the AJAX takes.

What does ‘Element is not clickable at point’ mean?

It means the element is covered by another element (like a modal or a fixed header). Scroll it into view with driver.execute_script("arguments[0].scrollIntoView();", element) or wait for the overlay to disappear.

Can I use implicit and explicit waits together?

Yes, but be careful. Implicit waits apply globally, while explicit waits override them for specific calls. Mixing can cause unpredictable wait times; it’s often cleaner to stick to explicit waits only.

Why does my test fail only when run with other tests?

This usually indicates test pollution – one test leaves the browser in a state that affects the next. Ensure each test has a fresh driver and resets application state (e.g., cookies, local storage) in the fixture.

How do I debug a test that hangs indefinitely?

Set a timeout on the WebDriverWait (e.g., 10 seconds) and use pytest-timeout to kill the test after a certain duration. Check for infinite loops in your code or a page that never finishes loading.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →