-
Notifications
You must be signed in to change notification settings - Fork 189
test: GP Test automation - removed duplicate entries in the report and updated log entries. #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
467b57f
GP Test automation - removed duplicate entries.
Bangarraju-Microsoft f3a394c
pylint error resolved
Bangarraju-Microsoft 639f16a
linting issues
Bangarraju-Microsoft 47db719
resolved comments
Bangarraju-Microsoft ab7c81b
lint issues
Bangarraju-Microsoft dc52712
Pylint issue
Bangarraju-Microsoft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,100 +1,121 @@ | ||
| """ | ||
| Pytest configuration for browser-based testing with Playwright and HTML report customization. | ||
| """ | ||
|
|
||
| import os | ||
| import atexit | ||
| import io | ||
| from bs4 import BeautifulSoup | ||
| import pytest | ||
| import atexit | ||
| import logging | ||
| from config.constants import URL | ||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
| from bs4 import BeautifulSoup | ||
| from playwright.sync_api import sync_playwright | ||
|
|
||
| from config.constants import URL | ||
|
|
||
| # Global dictionary to store log streams for each test | ||
| LOG_STREAMS = {} | ||
|
|
||
|
|
||
| @pytest.fixture(scope="session") | ||
| def login_logout(): | ||
| # perform login and browser close once in a session | ||
| with sync_playwright() as p: | ||
| browser = p.chromium.launch(headless=False, args=["--start-maximized"]) | ||
| """ | ||
| Fixture to launch the browser, log in, and yield the page object. | ||
| Closes the browser after the session ends. | ||
| """ | ||
| with sync_playwright() as playwright: | ||
| browser = playwright.chromium.launch(headless=False, args=["--start-maximized"]) | ||
| context = browser.new_context(no_viewport=True) | ||
| context.set_default_timeout(80000) | ||
| page = context.new_page() | ||
| # Navigate to the login URL | ||
|
|
||
| page.goto(URL, wait_until="domcontentloaded") | ||
| # login to web url with username and password | ||
|
|
||
| # Uncomment and complete the following to enable login | ||
| # login_page = LoginPage(page) | ||
| # load_dotenv() | ||
| # login_page.authenticate(os.getenv('user_name'), os.getenv('pass_word')) | ||
| # login_page.authenticate(os.getenv("user_name"), os.getenv("pass_word")) | ||
|
|
||
| yield page | ||
| # perform close the browser | ||
|
|
||
| browser.close() | ||
|
|
||
| log_streams = {} | ||
|
|
||
| @pytest.hookimpl(tryfirst=True) | ||
| def pytest_runtest_setup(item): | ||
| # Prepare StringIO for capturing logs | ||
| """ | ||
| Pytest hook to set up a log capture for each test. | ||
| """ | ||
| stream = io.StringIO() | ||
| handler = logging.StreamHandler(stream) | ||
| handler.setLevel(logging.INFO) | ||
|
|
||
| logger = logging.getLogger() | ||
| logger.addHandler(handler) | ||
|
|
||
| # Save handler and stream | ||
| log_streams[item.nodeid] = (handler, stream) | ||
| LOG_STREAMS[item.nodeid] = (handler, stream) | ||
|
|
||
|
|
||
| @pytest.hookimpl(hookwrapper=True) | ||
| def pytest_runtest_makereport(item, call): | ||
| """ | ||
| Pytest hook to add captured logs to the test report. | ||
| """ | ||
| outcome = yield | ||
| report = outcome.get_result() | ||
|
|
||
| handler, stream = log_streams.get(item.nodeid, (None, None)) | ||
| handler, stream = LOG_STREAMS.get(item.nodeid, (None, None)) | ||
|
|
||
| if handler and stream: | ||
| # Make sure logs are flushed | ||
| handler.flush() | ||
| log_output = stream.getvalue() | ||
|
|
||
| # Only remove the handler, don't close the stream yet | ||
| logger = logging.getLogger() | ||
| logger.removeHandler(handler) | ||
|
|
||
| # Store the log output on the report object for HTML reporting | ||
| report.description = f"<pre>{log_output.strip()}</pre>" | ||
|
|
||
| # Clean up references | ||
| log_streams.pop(item.nodeid, None) | ||
| LOG_STREAMS.pop(item.nodeid, None) | ||
| else: | ||
| report.description = "" | ||
|
|
||
|
|
||
| def pytest_collection_modifyitems(items): | ||
| """ | ||
| Modify test node IDs based on the test's parameterized 'prompt' value. | ||
| """ | ||
| for item in items: | ||
| if hasattr(item, 'callspec'): | ||
| if hasattr(item, "callspec"): | ||
| prompt = item.callspec.params.get("prompt") | ||
| if prompt: | ||
| item._nodeid = prompt # This controls how the test name appears in the report | ||
| item._nodeid = prompt | ||
|
|
||
|
|
||
| def rename_duration_column(): | ||
| report_path = os.path.abspath("report.html") # or your report filename | ||
| if not os.path.exists(report_path): | ||
| """ | ||
| Modify the HTML report to rename 'Duration' column to 'Execution Time'. | ||
| Runs automatically after the test session. | ||
| """ | ||
| report_path = Path("report.html") | ||
| if not report_path.exists(): | ||
| print("Report file not found, skipping column rename.") | ||
| return | ||
|
|
||
| with open(report_path, 'r', encoding='utf-8') as f: | ||
| soup = BeautifulSoup(f, 'html.parser') | ||
| with report_path.open("r", encoding="utf-8") as file: | ||
| soup = BeautifulSoup(file, "html.parser") | ||
|
|
||
| # Find and rename the header | ||
| headers = soup.select('table#results-table thead th') | ||
| headers = soup.select("table#results-table thead th") | ||
| for th in headers: | ||
| if th.text.strip() == 'Duration': | ||
| th.string = 'Execution Time' | ||
| #print("Renamed 'Duration' to 'Execution Time'") | ||
| if th.text.strip() == "Duration": | ||
| th.string = "Execution Time" | ||
| break | ||
| else: | ||
| print("'Duration' column not found in report.") | ||
|
|
||
| with open(report_path, 'w', encoding='utf-8') as f: | ||
| f.write(str(soup)) | ||
| with report_path.open("w", encoding="utf-8") as file: | ||
| file.write(str(soup)) | ||
|
|
||
|
|
||
| # Register this function to run after everything is done | ||
| # Register HTML report column modification | ||
| atexit.register(rename_duration_column) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,76 @@ | ||
| import logging | ||
| import time | ||
| import pytest | ||
| from pages.HomePage import HomePage | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| # Define step-wise test actions for Golden Path | ||
| golden_path_steps = [ | ||
| ("Validate home page is loaded", lambda home: home.validate_home_page()), | ||
| ("Select Invoice Schema", lambda home: home.select_schema("Invoice")), | ||
| ("Select Invoice Schema", lambda home: home.select_schema("Invoice")), | ||
| ("Upload Invoice documents", lambda home: home.upload_files("Invoice")), | ||
| ("Refresh page till status is updated to Completed", lambda home: home.refresh()), | ||
| ("Validate extracted result for Invoice", lambda home: home.validate_invoice_extracted_result()), | ||
| ("Modify Extracted Data JSON & submit comments", lambda home: home.modify_and_submit_extracted_data()), | ||
| ("Refreshing the page until the 'Invoice' file status is updated to 'Completed'", lambda home: home.refresh()), | ||
| ( | ||
| "Validate extracted result for Invoice", | ||
| lambda home: home.validate_invoice_extracted_result(), | ||
| ), | ||
| ( | ||
| "Modify Extracted Data JSON & submit comments", | ||
| lambda home: home.modify_and_submit_extracted_data(), | ||
| ), | ||
| ("Validate process steps for Invoice", lambda home: home.validate_process_steps()), | ||
| ("Select Property Loss Damage Claim Form Schema", lambda home: home.select_schema("Property")), | ||
| ("Upload Property Loss Damage Claim Form documents", lambda home: home.upload_files("Property")), | ||
| ("Refresh page till status is updated to Completed", lambda home: home.refresh()), | ||
| ("Validate extracted result for Property Loss Damage Claim Form", lambda home: home.validate_property_extracted_result()), | ||
| ("Validate process steps for Property Loss Damage Claim Form", lambda home: home.validate_process_steps()), | ||
| ("Validate Delete files", lambda home: home.delete_files()) | ||
| ( | ||
| "Select Property Loss Damage Claim Form Schema", | ||
| lambda home: home.select_schema("Property"), | ||
| ), | ||
| ( | ||
| "Upload Property Loss Damage Claim Form documents", | ||
| lambda home: home.upload_files("Property"), | ||
| ), | ||
| ("Refreshing the page until the 'Claim Form' status is updated to 'Completed'", lambda home: home.refresh()), | ||
| ( | ||
| "Validate extracted result for Property Loss Damage Claim Form", | ||
| lambda home: home.validate_property_extracted_result(), | ||
| ), | ||
| ( | ||
| "Validate process steps for Property Loss Damage Claim Form", | ||
| lambda home: home.validate_process_steps(), | ||
| ), | ||
| ("Validate user able to delete file", lambda home: home.delete_files()), | ||
| ] | ||
|
|
||
| # Generate readable test step IDs | ||
| golden_path_ids = [f"{i+1:02d}. {desc}" for i, (desc, _) in enumerate(golden_path_steps)] | ||
| golden_path_ids = [ | ||
| f"{i+1:02d}. {desc}" for i, (desc, _) in enumerate(golden_path_steps) | ||
| ] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("description, action", golden_path_steps, ids=golden_path_ids) | ||
| def test_content_processing_steps(login_logout, description, action, request): | ||
| """ | ||
| Executes Golden Path content processing steps with individual log entries. | ||
| """ | ||
| request.node._nodeid = description | ||
|
|
||
| page = login_logout | ||
| home = HomePage(page) | ||
|
|
||
| logger.info(f"Running test step: {description}") | ||
|
|
||
| start_time = time.time() | ||
|
|
||
| try: | ||
| action(home) | ||
| except Exception as e: | ||
| logger.error(f"Step failed: {description}") | ||
| duration = time.time() - start_time | ||
| logger.info(f"Step passed: {description} (Duration: {duration:.2f} seconds)") | ||
|
Bangarraju-Microsoft marked this conversation as resolved.
Outdated
|
||
| request.node._report_sections.append( | ||
| ("call", "log", f"Step passed: {description} (Duration: {duration:.2f} seconds)") | ||
| ) | ||
| except Exception: | ||
| duration = time.time() - start_time | ||
| logger.error(f"Step failed: {description} (Duration: {duration:.2f} seconds)") | ||
| raise | ||
|
|
||
| # Optionally attach to report | ||
|
|
||
| request.node._nodeid = description | ||
|
|
||
|
Bangarraju-Microsoft marked this conversation as resolved.
Outdated
|
||
| request.node._report_sections.append(("call", "log", f"Step passed: {description}")) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.