0
0
Testing Fundamentalstesting~15 mins

Risk-based testing in Testing Fundamentals - Build an Automation Script

Choose your learning style9 modes available
Risk-based testing for login functionality
Preconditions (2)
Step 1: Identify high-risk areas: login page and authentication process
Step 2: Test login with valid username and password
Step 3: Test login with invalid username
Step 4: Test login with invalid password
Step 5: Test login with empty username and password fields
Step 6: Test login with SQL injection attempt in username field
Step 7: Test login with very long input in username and password fields
✅ Expected Result: Login succeeds only with valid credentials; all invalid or malicious inputs are rejected with appropriate error messages; no system crashes or security breaches occur
Automation Requirements - Selenium with Python
Assertions Needed:
Verify successful login redirects to dashboard URL
Verify error message is displayed for invalid username
Verify error message is displayed for invalid password
Verify error message is displayed for empty fields
Verify error message is displayed for SQL injection attempt
Verify error message is displayed for very long inputs
Best Practices:
Use explicit waits to handle page loading
Use Page Object Model to separate page locators and actions
Use descriptive assertion messages
Avoid hardcoded waits like sleep
Use meaningful locators (id, name, or accessible attributes)
Automated Solution
Testing Fundamentals
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import unittest

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.username_input = (By.ID, 'username')
        self.password_input = (By.ID, 'password')
        self.login_button = (By.ID, 'loginBtn')
        self.error_message = (By.ID, 'errorMsg')

    def enter_username(self, username):
        self.driver.find_element(*self.username_input).clear()
        self.driver.find_element(*self.username_input).send_keys(username)

    def enter_password(self, password):
        self.driver.find_element(*self.password_input).clear()
        self.driver.find_element(*self.password_input).send_keys(password)

    def click_login(self):
        self.driver.find_element(*self.login_button).click()

    def get_error_message(self):
        return self.driver.find_element(*self.error_message).text

class TestRiskBasedLogin(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.get('https://example.com/login')
        self.wait = WebDriverWait(self.driver, 10)
        self.login_page = LoginPage(self.driver)

    def tearDown(self):
        self.driver.quit()

    def test_valid_login(self):
        self.login_page.enter_username('user1')
        self.login_page.enter_password('Password123!')
        self.login_page.click_login()
        self.wait.until(EC.url_contains('/dashboard'))
        self.assertIn('/dashboard', self.driver.current_url, 'Dashboard URL not loaded after valid login')

    def test_invalid_username(self):
        self.login_page.enter_username('wronguser')
        self.login_page.enter_password('Password123!')
        self.login_page.click_login()
        self.wait.until(EC.visibility_of_element_located(self.login_page.error_message))
        error = self.login_page.get_error_message()
        self.assertIn('Invalid username', error, 'Error message for invalid username not shown')

    def test_invalid_password(self):
        self.login_page.enter_username('user1')
        self.login_page.enter_password('WrongPass!')
        self.login_page.click_login()
        self.wait.until(EC.visibility_of_element_located(self.login_page.error_message))
        error = self.login_page.get_error_message()
        self.assertIn('Invalid password', error, 'Error message for invalid password not shown')

    def test_empty_fields(self):
        self.login_page.enter_username('')
        self.login_page.enter_password('')
        self.login_page.click_login()
        self.wait.until(EC.visibility_of_element_located(self.login_page.error_message))
        error = self.login_page.get_error_message()
        self.assertIn('Username and password required', error, 'Error message for empty fields not shown')

    def test_sql_injection_attempt(self):
        self.login_page.enter_username("' OR '1'='1")
        self.login_page.enter_password('Password123!')
        self.login_page.click_login()
        self.wait.until(EC.visibility_of_element_located(self.login_page.error_message))
        error = self.login_page.get_error_message()
        self.assertIn('Invalid username', error, 'Error message for SQL injection attempt not shown')

    def test_very_long_input(self):
        long_input = 'a' * 500
        self.login_page.enter_username(long_input)
        self.login_page.enter_password(long_input)
        self.login_page.click_login()
        self.wait.until(EC.visibility_of_element_located(self.login_page.error_message))
        error = self.login_page.get_error_message()
        self.assertIn('Input too long', error, 'Error message for very long input not shown')

if __name__ == '__main__':
    unittest.main()

The code uses Selenium with Python's unittest framework to automate risk-based testing of the login page.

The LoginPage class follows the Page Object Model pattern, storing locators and actions for the login page. This keeps the test code clean and maintainable.

Each test method targets a specific risk identified in the manual test case: valid login, invalid username, invalid password, empty fields, SQL injection attempt, and very long inputs.

Explicit waits (WebDriverWait) ensure the test waits for page elements or URL changes before asserting, avoiding flaky tests.

Assertions check for correct URL or error messages with clear messages to help diagnose failures.

The setup and teardown methods open and close the browser for each test, ensuring a fresh start.

Common Mistakes - 4 Pitfalls
Using time.sleep() instead of explicit waits
Using brittle XPath selectors that break easily
Mixing test logic and page locators in the same code
{'mistake': 'Not verifying error messages for invalid inputs', 'why_bad': "Missing verification means you don't know if the system handles errors properly.", 'correct_approach': 'Assert that appropriate error messages appear for each invalid input.'}
Bonus Challenge

Now add data-driven testing with 3 different sets of invalid credentials to verify error handling.

Show Hint