Why Agile changes testing dynamics in Testing Fundamentals - Automation Benefits in Action
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 AgileSprintTesting(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.get('https://agile-tool.example.com/login') self.wait = WebDriverWait(self.driver, 10) # Login self.driver.find_element(By.ID, 'username').send_keys('tester') self.driver.find_element(By.ID, 'password').send_keys('TestPass123') self.driver.find_element(By.ID, 'login-btn').click() def test_agile_sprint_testing(self): driver = self.driver wait = self.wait # Navigate to current sprint backlog wait.until(EC.element_to_be_clickable((By.ID, 'sprint-backlog-link'))).click() # Select user story with status 'Ready for Testing' user_stories = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.user-story'))) target_story = None for story in user_stories: status = story.find_element(By.CSS_SELECTOR, '.status').text if status == 'Ready for Testing': target_story = story break self.assertIsNotNone(target_story, 'No user story with status Ready for Testing found') # Open user story details target_story.find_element(By.CSS_SELECTOR, '.details-btn').click() # Execute test cases test_cases = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.test-case'))) for test_case in test_cases: test_case.find_element(By.CSS_SELECTOR, '.execute-btn').click() # Wait for execution result result = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.execution-result'))).text self.assertIn(result, ['Pass', 'Fail'], 'Execution result should be Pass or Fail') if result == 'Fail': # Log defect test_case.find_element(By.CSS_SELECTOR, '.log-defect-btn').click() defect_desc = wait.until(EC.visibility_of_element_located((By.ID, 'defect-description'))) defect_desc.send_keys('Automated defect logged during test execution') driver.find_element(By.ID, 'submit-defect-btn').click() # Update test status to Passed if no defects defects = driver.find_elements(By.CSS_SELECTOR, '.defect') if len(defects) == 0: driver.find_element(By.ID, 'update-status-btn').click() status_text = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.status'))).text self.assertEqual(status_text, 'Passed', 'Test status should update to Passed') # Verify sprint dashboard shows updated results driver.find_element(By.ID, 'sprint-dashboard-link').click() dashboard_status = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, f'.user-story-status[data-story-id="{target_story.get_attribute("data-id")}"]'))).text self.assertIn(dashboard_status, ['Passed', 'Failed'], 'Sprint dashboard should show updated test status') def tearDown(self): self.driver.quit() if __name__ == '__main__': unittest.main()
This test script automates the Agile sprint testing process using Selenium with Python.
Setup: Opens the browser, navigates to the Agile tool login page, and logs in with test credentials.
Test Steps: Navigates to the current sprint backlog, finds a user story ready for testing, executes its test cases, logs defects if any test fails, updates the test status to 'Passed' if no defects, and verifies the sprint dashboard reflects the updated status.
Assertions: Check that the user story is ready for testing, test execution results are valid, defects can be logged, status updates correctly, and dashboard shows the latest status.
Best Practices: Uses explicit waits to handle dynamic elements, uses clear selectors, and includes meaningful assertion messages to help identify issues.
Now add data-driven testing with 3 different user stories having different statuses