diff --git a/tests/e2e-test/tests/conftest.py b/tests/e2e-test/tests/conftest.py index e43ff21d..a6459bf2 100644 --- a/tests/e2e-test/tests/conftest.py +++ b/tests/e2e-test/tests/conftest.py @@ -1,37 +1,52 @@ -import os -import atexit +""" +Pytest configuration for browser-based testing with Playwright and HTML report customization. +""" + import io -from bs4 import BeautifulSoup -import pytest +import atexit import logging -from config.constants import URL +from pathlib import Path +from venv import logger + +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) @@ -39,62 +54,68 @@ def pytest_runtest_setup(item): 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"
{log_output.strip()}"
- # 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):
- print("Report file not found, skipping column rename.")
+ """
+ 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():
+ logger.info("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)
diff --git a/tests/e2e-test/tests/test_contentProcessing_gp_tc.py b/tests/e2e-test/tests/test_contentProcessing_gp_tc.py
index d831cd43..7fe90c2c 100644
--- a/tests/e2e-test/tests/test_contentProcessing_gp_tc.py
+++ b/tests/e2e-test/tests/test_contentProcessing_gp_tc.py
@@ -1,28 +1,49 @@
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)
@@ -31,16 +52,21 @@ 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
+ message = "Step passed: %s (Duration: %.2f seconds)" % (description, duration)
+ logger.info(message)
+ request.node._report_sections.append(("call", "log", message))
+
+ except Exception:
+ duration = time.time() - start_time
+ logger.error("Step failed: %s (Duration: %.2f seconds)", description, duration, exc_info=True)
raise
-
- # Optionally attach to report
request.node._report_sections.append(("call", "log", f"Step passed: {description}"))