From 4ef493749301ce22f5f9ed4068bcae24b5ccc54f Mon Sep 17 00:00:00 2001 From: Hani Yacoub Date: Fri, 30 May 2025 14:34:46 +0300 Subject: [PATCH 1/5] set smoke tests to smoke and sanity --- modules/testrail.py | 4 + ...ail_set_smoke_tests_to_smoke_and_sanity.py | 119 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 modules/testrail_set_smoke_tests_to_smoke_and_sanity.py diff --git a/modules/testrail.py b/modules/testrail.py index 9f2f71d6f..d0677d079 100644 --- a/modules/testrail.py +++ b/modules/testrail.py @@ -160,6 +160,10 @@ def get_test_case(self, case_id): """Get a given Test Case""" return self.client.send_get(f"get_case/{case_id}") + def get_suites(self, project_id): + """Get all suites for project""" + return self.client.send_get(f"get_suites/{project_id}") + def update_cases_in_suite(self, suite_id, case_ids, **kwargs): """Given a suite and a list of test cases, update all listed test cases according to keyword args""" diff --git a/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py b/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py new file mode 100644 index 000000000..e1e65c25d --- /dev/null +++ b/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py @@ -0,0 +1,119 @@ +import logging +from dotenv import load_dotenv +from modules.testrail_integration import testrail_init + +# Load environment variables from .env file +load_dotenv() + +# Configuration Constants +PROJECT_ID = 17 # The ID of the TestRail project to work with +SUITE_NAMES = ["PDF Viewer"] # List of suite names to process + +CUSTOM_SUB_TEST_SUITES = [2] # Value to set for the 'custom_sub_test_suites' field +TEST_SUB_SUITES = { + 1: "functional", + 2: "smoke", + 3: "accessibility", + 4: "l10n", + 5: "security", + 6: "fxa", + 7: "other" +} +updated_count = 0 +DRY_RUN = True # If True, only log actions without making changes + + +def get_all_cases_from_suite(tr, project_id, suite_id): + """ + Fetch all test cases from a given TestRail suite using pagination. + + Args: + tr: TestRail API client instance. + project_id (int): The ID of the TestRail project. + suite_id (int): The ID of the suite to fetch cases from. + + Returns: + list: A list of test case dictionaries. + """ + all_cases = [] # List to store all fetched test cases + offset = 0 # Starting point for pagination + limit = 240 # Maximum number of cases to fetch in each API call + + while True: + # Build the API endpoint with pagination parameters + endpoint = f"get_cases/{project_id}&suite_id={suite_id}&limit={limit}&offset={offset}" + response = tr.client.send_get(endpoint) # Send API request to TestRail + cases = response.get("cases", []) # Extract the list of test cases + + if not cases: + # If no more cases are found, break the loop + break + + # Add the fetched cases to the complete list + all_cases.extend(cases) + + if len(cases) < limit: + # If the number of fetched cases is less than the limit, we are at the last page + break + + # Increment offset to fetch the next batch of cases + offset += limit + + # Log the total number of fetched cases + logging.info(f"Total cases fetched from suite {suite_id}: {len(all_cases)}") + return all_cases + + +if __name__ == "__main__": + # Initialize logging to display info messages + logging.basicConfig(level=logging.INFO) + + # Initialize the TestRail API client + tr = testrail_init() + + # Fetch suite IDs matching the given suite names + suites = tr.get_suites(PROJECT_ID) + suite_ids = [suite["id"] for suite in suites if suite["name"] in SUITE_NAMES] + logging.info(f"Found suites: {suite_ids}") + + # Fetch all test cases from the selected suites + all_cases = [] # List to store all fetched test cases + for suite_id in suite_ids: + # Fetch and add cases from each suite + cases = get_all_cases_from_suite(tr, PROJECT_ID, suite_id) + all_cases.extend(cases) + + # Log the total number of test cases found + logging.info(f"Total test cases found for selected suites: {len(all_cases)}") + + updated_count = 0 # Counter for the number of cases updated + + # Iterate through all cases + for case in all_cases: + case_id = case["id"] + sub_test_suites_value = case.get("sub_test_suites", []) + + logging.info(f"Case ID {case_id} sub_test_suites: {sub_test_suites_value}") + + case_id = case["id"] + sub_test_suites_value = case.get("sub_test_suites", []) # Fallback to empty list + custom_value = case.get("custom_sub_test_suites", "Not Set") + + # Check if 2 is present in sub_test_suites + if 2 not in sub_test_suites_value: + logging.info(f"Skipping case {case_id} – sub_test_suites = {sub_test_suites_value}") + continue + + logging.info( + f"Case ID {case_id} matches (contains 2 in sub_test_suites). Current custom_sub_test_suites: {custom_value}") + + if not DRY_RUN: + # Perform the update + result = tr.update_case_field(case_id, "custom_sub_test_suites", CUSTOM_SUB_TEST_SUITES) + logging.info(f"Updated case {case_id} to '{CUSTOM_SUB_TEST_SUITES}', Result: {result}") + else: + logging.info(f"[DRY RUN] Would update case {case_id} from '{custom_value}' to '{CUSTOM_SUB_TEST_SUITES}'.") + + updated_count += 1 + + logging.info(f"Total cases {'updated' if not DRY_RUN else 'to be updated'}: {updated_count}") From 522e00a7bb5dcd320b18d37992e8070455f765a2 Mon Sep 17 00:00:00 2001 From: Hani Yacoub Date: Fri, 30 May 2025 16:32:46 +0300 Subject: [PATCH 2/5] edit code --- ...ail_set_smoke_tests_to_smoke_and_sanity.py | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py b/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py index e1e65c25d..dbb2481a1 100644 --- a/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py +++ b/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py @@ -10,15 +10,6 @@ SUITE_NAMES = ["PDF Viewer"] # List of suite names to process CUSTOM_SUB_TEST_SUITES = [2] # Value to set for the 'custom_sub_test_suites' field -TEST_SUB_SUITES = { - 1: "functional", - 2: "smoke", - 3: "accessibility", - 4: "l10n", - 5: "security", - 6: "fxa", - 7: "other" -} updated_count = 0 DRY_RUN = True # If True, only log actions without making changes @@ -91,29 +82,25 @@ def get_all_cases_from_suite(tr, project_id, suite_id): # Iterate through all cases for case in all_cases: case_id = case["id"] - sub_test_suites_value = case.get("sub_test_suites", []) - logging.info(f"Case ID {case_id} sub_test_suites: {sub_test_suites_value}") + type_id = case.get("type_id") + current_custom_value = case.get("custom_sub_test_suites", "Not Set") - case_id = case["id"] - sub_test_suites_value = case.get("sub_test_suites", []) # Fallback to empty list - custom_value = case.get("custom_sub_test_suites", "Not Set") + logging.info(f"Case ID {case_id} type_id: {type_id}") - # Check if 2 is present in sub_test_suites - if 2 not in sub_test_suites_value: - logging.info(f"Skipping case {case_id} – sub_test_suites = {sub_test_suites_value}") + if type_id != 6: + logging.info(f"Skipping case {case_id} – type_id = {type_id}") continue logging.info( - f"Case ID {case_id} matches (contains 2 in sub_test_suites). Current custom_sub_test_suites: {custom_value}") + f"Case ID {case_id} matches (type_id == 6). " + f"Current custom_sub_test_suites: {current_custom_value}" + ) if not DRY_RUN: - # Perform the update - result = tr.update_case_field(case_id, "custom_sub_test_suites", CUSTOM_SUB_TEST_SUITES) - logging.info(f"Updated case {case_id} to '{CUSTOM_SUB_TEST_SUITES}', Result: {result}") + result = tr.update_case_field(case_id, "custom_sub_test_suites", [2]) + logging.info(f"Updated case {case_id} to '[2]', Result: {result}") else: - logging.info(f"[DRY RUN] Would update case {case_id} from '{custom_value}' to '{CUSTOM_SUB_TEST_SUITES}'.") + logging.info(f"[DRY RUN] Would update case {case_id} from '{current_custom_value}' to '[2]'.") updated_count += 1 - - logging.info(f"Total cases {'updated' if not DRY_RUN else 'to be updated'}: {updated_count}") From 8def3ca16985aea50079fe90f1dba7aa8c1f3ee2 Mon Sep 17 00:00:00 2001 From: Hani Yacoub Date: Tue, 3 Jun 2025 16:46:09 +0300 Subject: [PATCH 3/5] Testrail change the sub test suite for all Automation Completed test cases into Smoke and Sanity --- ...oke_and_sanity_all_automation_completed.py | 125 ++++++++++++++++++ ...ail_set_smoke_tests_to_smoke_and_sanity.py | 106 --------------- 2 files changed, 125 insertions(+), 106 deletions(-) create mode 100644 modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py delete mode 100644 modules/testrail_set_smoke_tests_to_smoke_and_sanity.py diff --git a/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py new file mode 100644 index 000000000..fd8ec1813 --- /dev/null +++ b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py @@ -0,0 +1,125 @@ +import logging +from dotenv import load_dotenv +from modules.testrail_integration import testrail_init + +# Load environment variables from .env file (like API credentials) +load_dotenv() + +# Configuration Constants +PROJECT_ID = 17 # ID of the TestRail project to work with +SUITE_NAMES = [ + "Address Bar and Search", + "Audio/Video", + "Bookmarks and History", + "Downloads", + "Drag and Drop", + "Find Toolbar", + "Form Autofill", + "Geolocation", + "Language Packs", + "Menus", + "Networking", + "Notifications", + "PDF Viewer", + "Password Manager", + "Pocket", + "Preferences", + "Profile", + "Printing UI", + "Reader View", + "Scrolling", + "Security and Privacy", + "Sync & Firefox Account", + "Tabs", + "Theme and Toolbar", +] # Only process suites with this name + +CUSTOM_SUB_TEST_SUITES = [2] # Value to set for 'custom_sub_test_suites' field (e.g. 'Smoke') +DRY_RUN = True # If True, simulate updates without sending changes + + +def get_all_cases_from_suite(tr, project_id, suite_id): + """ + Fetch all test cases from a given TestRail suite using pagination. + + Args: + tr: TestRail API client instance. + project_id (int): The TestRail project ID. + suite_id (int): The specific suite ID within the project. + + Returns: + list: All test cases as a list of dictionaries. + """ + all_cases = [] # List to hold all fetched cases + offset = 0 # Pagination offset + limit = 240 # API fetch limit per request + + while True: + # Build API URL with pagination + endpoint = f"get_cases/{project_id}&suite_id={suite_id}&limit={limit}&offset={offset}" + response = tr.client.send_get(endpoint) + cases = response.get("cases", []) + + if not cases: + # Break loop when no more cases are returned + break + + all_cases.extend(cases) + + # If we receive less than the limit, it means we've reached the last page + if len(cases) < limit: + break + + offset += limit # Move to next page + + logging.info(f"Total cases fetched from suite {suite_id}: {len(all_cases)}") + return all_cases + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) # Enable info-level logging + tr = testrail_init() # Initialize the TestRail client + + # Get all suites for the project and filter the ones we need + suites = tr.get_suites(PROJECT_ID) + suite_ids = [suite["id"] for suite in suites if suite["name"] in SUITE_NAMES] + logging.info(f"Found suites: {suite_ids}") + + # Gather all test cases from selected suites + all_cases = [] + for suite_id in suite_ids: + cases = get_all_cases_from_suite(tr, PROJECT_ID, suite_id) + all_cases.extend(cases) + + logging.info(f"Total test cases found for selected suites: {len(all_cases)}") + + updated_count = 0 # Track how many cases we updated + + # Iterate over all test cases + for case in all_cases: + case_id = case["id"] + automation_status = case.get("custom_automation_status") # Read the automation status field + current_custom_value = case.get("custom_sub_test_suites", "Not Set") # Read current custom field value + + logging.info(f"Case ID {case_id} custom_automation_status: {automation_status}") + + # Only proceed if the custom automation status equals 4 (4 = Completed) + if automation_status != 4: + logging.info(f"Skipping case {case_id} – custom_automation_status = {automation_status}") + continue + + logging.info( + f"Case ID {case_id} matches (custom_automation_status == 4). " + f"Current custom_sub_test_suites: {current_custom_value}" + ) + + # Update the field if not in dry run mode + if not DRY_RUN: + result = tr.update_case_field(case_id, "custom_sub_test_suites", [2]) + logging.info(f"Updated case {case_id} to '[2]', Result: {result}") + else: + logging.info(f"[DRY RUN] Would update case {case_id} from '{current_custom_value}' to '[2]'.") + + updated_count += 1 # Count how many updates we made (or would have made) + + logging.info(f"Total cases {'updated' if not DRY_RUN else 'to be updated'}: {updated_count}") diff --git a/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py b/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py deleted file mode 100644 index dbb2481a1..000000000 --- a/modules/testrail_set_smoke_tests_to_smoke_and_sanity.py +++ /dev/null @@ -1,106 +0,0 @@ -import logging -from dotenv import load_dotenv -from modules.testrail_integration import testrail_init - -# Load environment variables from .env file -load_dotenv() - -# Configuration Constants -PROJECT_ID = 17 # The ID of the TestRail project to work with -SUITE_NAMES = ["PDF Viewer"] # List of suite names to process - -CUSTOM_SUB_TEST_SUITES = [2] # Value to set for the 'custom_sub_test_suites' field -updated_count = 0 -DRY_RUN = True # If True, only log actions without making changes - - -def get_all_cases_from_suite(tr, project_id, suite_id): - """ - Fetch all test cases from a given TestRail suite using pagination. - - Args: - tr: TestRail API client instance. - project_id (int): The ID of the TestRail project. - suite_id (int): The ID of the suite to fetch cases from. - - Returns: - list: A list of test case dictionaries. - """ - all_cases = [] # List to store all fetched test cases - offset = 0 # Starting point for pagination - limit = 240 # Maximum number of cases to fetch in each API call - - while True: - # Build the API endpoint with pagination parameters - endpoint = f"get_cases/{project_id}&suite_id={suite_id}&limit={limit}&offset={offset}" - response = tr.client.send_get(endpoint) # Send API request to TestRail - cases = response.get("cases", []) # Extract the list of test cases - - if not cases: - # If no more cases are found, break the loop - break - - # Add the fetched cases to the complete list - all_cases.extend(cases) - - if len(cases) < limit: - # If the number of fetched cases is less than the limit, we are at the last page - break - - # Increment offset to fetch the next batch of cases - offset += limit - - # Log the total number of fetched cases - logging.info(f"Total cases fetched from suite {suite_id}: {len(all_cases)}") - return all_cases - - -if __name__ == "__main__": - # Initialize logging to display info messages - logging.basicConfig(level=logging.INFO) - - # Initialize the TestRail API client - tr = testrail_init() - - # Fetch suite IDs matching the given suite names - suites = tr.get_suites(PROJECT_ID) - suite_ids = [suite["id"] for suite in suites if suite["name"] in SUITE_NAMES] - logging.info(f"Found suites: {suite_ids}") - - # Fetch all test cases from the selected suites - all_cases = [] # List to store all fetched test cases - for suite_id in suite_ids: - # Fetch and add cases from each suite - cases = get_all_cases_from_suite(tr, PROJECT_ID, suite_id) - all_cases.extend(cases) - - # Log the total number of test cases found - logging.info(f"Total test cases found for selected suites: {len(all_cases)}") - - updated_count = 0 # Counter for the number of cases updated - - # Iterate through all cases - for case in all_cases: - case_id = case["id"] - - type_id = case.get("type_id") - current_custom_value = case.get("custom_sub_test_suites", "Not Set") - - logging.info(f"Case ID {case_id} type_id: {type_id}") - - if type_id != 6: - logging.info(f"Skipping case {case_id} – type_id = {type_id}") - continue - - logging.info( - f"Case ID {case_id} matches (type_id == 6). " - f"Current custom_sub_test_suites: {current_custom_value}" - ) - - if not DRY_RUN: - result = tr.update_case_field(case_id, "custom_sub_test_suites", [2]) - logging.info(f"Updated case {case_id} to '[2]', Result: {result}") - else: - logging.info(f"[DRY RUN] Would update case {case_id} from '{current_custom_value}' to '[2]'.") - - updated_count += 1 From 96c5cf9f8c4a85eb9b1b5d8a7d74dea8dffa9c72 Mon Sep 17 00:00:00 2001 From: Hani Yacoub Date: Wed, 4 Jun 2025 16:40:25 +0300 Subject: [PATCH 4/5] edit suite names --- ...oke_and_sanity_all_automation_completed.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py index fd8ec1813..622be9e6e 100644 --- a/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py +++ b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py @@ -8,9 +8,12 @@ # Configuration Constants PROJECT_ID = 17 # ID of the TestRail project to work with SUITE_NAMES = [ - "Address Bar and Search", + "Address Bar 138+", + "Address Bar and Search <136 (to use with late beta) - locked", + "Address Bar and Search Scotch Bonnet (to use with early beta)", "Audio/Video", "Bookmarks and History", + "Build Branding", "Downloads", "Drag and Drop", "Find Toolbar", @@ -19,19 +22,18 @@ "Language Packs", "Menus", "Networking", - "Notifications", + "Notifications, Push Notifications and Alerts", "PDF Viewer", - "Password Manager", - "Pocket", + "Password manager", "Preferences", - "Profile", - "Printing UI", + "Printing", "Reader View", - "Scrolling", + "Scrolling, Panning and Zooming", "Security and Privacy", + "Startup and Profile", "Sync & Firefox Account", - "Tabs", - "Theme and Toolbar", + "Tabbed Browser", + "Theme and Toolbar Customization" ] # Only process suites with this name CUSTOM_SUB_TEST_SUITES = [2] # Value to set for 'custom_sub_test_suites' field (e.g. 'Smoke') From fd672a14df86e205bd980ea2f8c6a80870990041 Mon Sep 17 00:00:00 2001 From: Hani Yacoub Date: Thu, 5 Jun 2025 14:52:09 +0300 Subject: [PATCH 5/5] add website --- ...strail_change_to_smoke_and_sanity_all_automation_completed.py | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py index 622be9e6e..242744650 100644 --- a/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py +++ b/modules/testrail_scripts/testrail_change_to_smoke_and_sanity_all_automation_completed.py @@ -8,6 +8,7 @@ # Configuration Constants PROJECT_ID = 17 # ID of the TestRail project to work with SUITE_NAMES = [ + "[QA-2617] Nimbus Scotch Bonnet", "Address Bar 138+", "Address Bar and Search <136 (to use with late beta) - locked", "Address Bar and Search Scotch Bonnet (to use with early beta)",