How to perform Negative Testing with Selenium and Python?

Negative Testing for Web Forms: What, Why, and How

Introduction

Every application faces one critical challenge—how to handle invalid inputs. While positive testing ensures the application behaves correctly with valid data, negative testing checks how it handles invalid, unexpected, or malicious inputs. This is especially important for web forms, the most common interface for user input.

With Selenium and Python, you can automate negative testing efficiently, saving time and ensuring your application meets real-world expectations. In this guide, we’ll explore:

  • What negative testing is.
  • Why it’s essential for web forms.
  • How to implement it with Selenium and Python.

1. What is Negative Testing?

Negative testing is a process of providing invalid or unexpected data to an application to test its robustness. The goal is to verify that:

  • Invalid inputs are rejected.
  • Proper error messages guide users.
  • The system doesn’t crash or behave unpredictably.

Example Scenarios

In the context of form submissions, negative testing might involve:

  1. Leaving mandatory fields empty.
  2. Providing an email address without an @ symbol.
  3. Entering text into a field meant for numbers.
  4. Submitting special characters in name fields.

Negative testing simulates real-world scenarios, including user mistakes and malicious attacks.

2. Why is Negative Testing Essential for Web Forms?

Enhances Security

Web forms are the most common entry point for attacks like SQL injection and cross-site scripting (XSS). Negative testing helps block malicious inputs.

Improves User Experience

By validating error messages, negative testing ensures that users receive clear, actionable feedback when they make mistakes.

Prevents Crashes

Unexpected inputs can cause applications to crash or behave unpredictably. Negative testing ensures the system remains stable under such conditions.

Real-World Readiness

No matter how foolproof your application seems, users will find a way to input invalid data. Negative testing prepares your system for such scenarios.

3. How to Implement Negative Testing with Selenium and Python

Step 1: Analyze the Form

Before automating tests, identify:

  • Mandatory fields: Which fields must be filled?
  • Validation rules: What formats are acceptable (e.g., email, phone numbers)?
  • Expected error messages: How does the system respond to invalid data?

Step 2: Write Negative Test Cases

Below are examples of negative test cases for a sample form:

Test CaseInputExpected Behavior
Missing NameName: ""Display: “Name is required”
Invalid EmailEmail: "invalid-email@"Display: “Invalid email”
Unsupported URLWebsite: "not-a-url"Display: “Enter a valid URL”
Special CharactersName: "@#!$%^"Display: “Invalid characters”
Missing MandatoryAll fields emptyDisplay: “All fields required”

Step 3: Automate Negative Test Cases with Selenium

Here’s a Python script that automates these negative tests:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import time

# Function to safely interact with elements
def safe_find_element(driver, by, value, description):
    try:
        element = driver.find_element(by, value)
        return element
    except NoSuchElementException:
        print(f"Element not found: {description} ({value})")
        return None

# Function to check if a dropdown option exists
def option_exists(select_element, option_text):
    for option in select_element.options:
        if option.text == option_text:
            return True
    return False

# Function to automate testing with result validation
def automate_test_case(data, expected_result, driver_path):
    driver = webdriver.Chrome()
    driver.get("https://training.qaonlinetraining.com/testPage.php")
    actual_result = ""

    try:
        # Fill 'Name' field
        if data.get("name") is not None:
            name_field = safe_find_element(driver, By.NAME, "name", "Name field")
            if name_field:
                name_field.clear()
                name_field.send_keys(data["name"])

        # Fill 'E-mail' field
        if data.get("email") is not None:
            email_field = safe_find_element(driver, By.NAME, "email", "Email field")
            if email_field:
                email_field.clear()
                email_field.send_keys(data["email"])

        # Fill 'Website' field
        if data.get("website"):
            website_field = safe_find_element(driver, By.NAME, "website", "Website field")
            if website_field:
                website_field.clear()
                website_field.send_keys(data["website"])

        # Fill 'Comment' field
        if data.get("comment"):
            comment_field = safe_find_element(driver, By.NAME, "comment", "Comment field")
            if comment_field:
                comment_field.clear()
                comment_field.send_keys(data["comment"])

        # Select 'Gender'
        if data.get("gender") in ["female", "male", "Other"]:
            gender_radio = safe_find_element(driver, By.XPATH, f"//input[@name='gender'][@value='{data['gender']}']", "Gender radio button")
            if gender_radio:
                gender_radio.click()

        # Select 'Country'
        if data.get("country"):
            country_select_element = safe_find_element(driver, By.NAME, "country", "Country dropdown")
            if country_select_element:
                select = Select(country_select_element)
                if option_exists(select, data["country"]):
                    select.select_by_visible_text(data["country"])
                else:
                    print(f"Invalid country: {data['country']} is not an available option.")
                    actual_result = "error"

        # Submit the form
        submit_button = safe_find_element(driver, By.NAME, "submit", "Submit button")
        if submit_button:
            submit_button.click()

            # Capture the page response to determine success or error
            time.sleep(2)  # Wait for the page to load or update
            if "is required" in driver.page_source.lower() or "invalid" in driver.page_source.lower():
                actual_result = "error"
            else:
                actual_result = "success"

    except Exception as e:
        actual_result = "error"
        print(f"Exception occurred during test execution: {e}")
    finally:
        driver.quit()

    # Compare actual and expected results
    if actual_result == expected_result:
        print(f"Test Passed: Expected '{expected_result}', got '{actual_result}'.")
    else:
        print(f"Test Failed: Expected '{expected_result}', got '{actual_result}'.")

# Main script for test cases
if __name__ == "__main__":
    # Define test cases with expected outcomes
    test_cases = [
        {
            "data": {
                "name": "John Doe",
                "email": "john.doe@example.com",
                "website": "https://johndoe.com",
                "comment": "Looking forward to the training!",
                "gender": "male",
                "country": "USA",
            },
            "expected_result": "success",  # Positive test case
        },
        {
            "data": {
                "name": "",
                "email": "invalid-email@",  # Invalid email
                "website": "http://invalid-website",
                "comment": "Testing invalid inputs.",
                "gender": "InvalidGender",  # Invalid gender
                "country": "InvalidCountry",  # Invalid country
            },
            "expected_result": "error",  # Negative test case
        },
        {
            "data": {
                "name": "John",
                "email": "no-domain-email",  # Invalid email
                "website": None,
                "comment": "",
                "gender": None,  # No gender selected
                "country": None,  # No country selected
            },
            "expected_result": "error",  # Negative test case
        },
    ]

    # Path to ChromeDriver (update this to the correct path)
    CHROME_DRIVER_PATH = "/path/to/chromedriver"

    # Execute test cases
    for i, test_case in enumerate(test_cases, 1):
        print(f"\nExecuting Test Case {i}...")
        automate_test_case(test_case["data"], test_case["expected_result"], CHROME_DRIVER_PATH)

Result:

4. Best Practices for Negative Testing

  1. Cover Edge Cases: Test scenarios like extremely long inputs or unsupported characters.
  2. Use Explicit Waits: Avoid flakiness by waiting for dynamic elements to load.
  3. Automate Repetitive Tasks: Use loops and dynamic functions to minimize manual effort.
  4. Log Results: Ensure clear logs for passed and failed cases for better debugging.

5. Challenges in Negative Testing

Dynamic Error Messages

Some error messages change based on input. Use flexible validation methods to handle dynamic text.

Flaky Tests

Automation scripts may fail intermittently due to UI changes or network delays. Use proper timeouts and error handling.


Conclusion

Negative testing is a vital part of ensuring your web forms are secure, user-friendly, and reliable. With tools like Selenium and Python, automating these tests becomes efficient and scalable. By implementing the techniques and best practices outlined in this guide, you can master negative testing and elevate your QA workflows.

Start implementing these techniques today to make your applications robust and ready for real-world use!

Call-to-Action:
Ready to master DevOps testing? 🚀 Explore our Automation Testing Training Program today and build job-ready skills to stand out in the testing industry!

Explore our courses today and take the first step toward a rewarding career in software testing!

API Testing Training with Postman

Automation Testing with Selenium (Java) Training Program

Mobile testing training with Appium

Gain knowledge in software testing and elevate your skills to outperform competitors.

Training ProgramDemo TimingTraining FeesAction
Software Testing Online Certification TrainingDemo at 09:00 AM ETStarts at $1049Book your demo
Software Testing Classroom Training in VirginiaDemo at 01:00 PM ET every SundayStarts at $1699Book your demo
Selenium Certification TrainingDemo at 10:00 AM ETStarts at $550Book your demo
Manual Testing CourseDemo at 09:00 AM ETStarts at $400Book your demo
SDET Course – Software Automation Testing TrainingDemo at 11:00 AM ETStarts at $550Book your demo
Automation Testing Real-Time Project TrainingDemo at 10:00 AM ETStarts at $250Book your demo
Business Analyst CertificationDemo at 12:00 PM ETStarts at $550Book your demo

Search for QA Testing Jobs, Automation Roles, and more…