Skip to content

Commit

Permalink
add-tests-to-lobster-html-report
Browse files Browse the repository at this point in the history
  • Loading branch information
SurajBDeore committed Feb 3, 2025
1 parent e198124 commit 9daf37e
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 532 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ jobs:
run: |
python3 -m pip install --upgrade pip
python3 -m pip install -r requirements_dev.txt
make lobster/html/assets.py
- name: Install gnu make on macos
if: startsWith(matrix.os, 'macos')
run: |
Expand Down
25 changes: 3 additions & 22 deletions tests-UI/Makefile
Original file line number Diff line number Diff line change
@@ -1,34 +1,15 @@
# Makefile

# Tool paths
LOBSTER_PYTHON_TOOL := ../lobster-python
LOBSTER_REPORT_TOOL := ../lobster-report
LOBSTER_HTML_REPORT_TOOL := ../lobster-html-report

# Python script and configuration file
PYTHON_SCRIPT := ../lobster/tools/python/python.py
LOBSTER_CONFIG := lobster.config

# Output files
PYTHON_OUTPUT := python.lobster
REPORT_OUTPUT := report.lobster
REPORT_OUTPUT := report.output
HTML_REPORT_OUTPUT := test_html_report.html

# Default target
.PHONY: all
all: python-output report-output html-report-output selenium-tests clean

# Generate Python output
.PHONY: python-output
python-output:
@echo "Running lobster-python script on: $(PYTHON_SCRIPT)"
@python3 $(LOBSTER_PYTHON_TOOL) $(PYTHON_SCRIPT) --out=$(PYTHON_OUTPUT)

# Generate LOBSTER report
.PHONY: report-output
report-output:
@echo "Generating LOBSTER report..."
@python3 $(LOBSTER_REPORT_TOOL) --lobster-config=$(LOBSTER_CONFIG) --out=$(REPORT_OUTPUT)
all: html-report-output selenium-tests clean

# Generate HTML report
.PHONY: html-report-output
Expand All @@ -49,4 +30,4 @@ selenium-tests:
.PHONY: clean
clean:
@echo "Cleaning up generated files..."
@rm -f $(PYTHON_OUTPUT) $(REPORT_OUTPUT) $(HTML_REPORT_OUTPUT)
@rm -f $(HTML_REPORT_OUTPUT)
3 changes: 0 additions & 3 deletions tests-UI/lobster.config

This file was deleted.

90 changes: 90 additions & 0 deletions tests-UI/report.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
"schema": "lobster-report",
"version": 2,
"generator": "lobster_report",
"levels": [
{
"name": "code",
"kind": "implementation",
"items": [
{
"tag": "python python.count_occurrence_of_last_function_from_function_name_list",
"location": {
"kind": "github",
"gh_root": "https://github.com/bmw-software-engineering/lobster",
"commit": "main",
"file": "lobster\\tools\\python\\python.py",
"line": 40,
"exec_commit_id": "e1981245cb1c5064d42299b59f80f4e1c3c37901"
},
"name": "python.count_occurrence_of_last_function_from_function_name_list",
"messages": [],
"just_up": [],
"just_down": [],
"just_global": [],
"tracing_status": "OK",
"language": "Python",
"kind": "Function"
},
{
"tag": "python python.parse_value",
"location": {
"kind": "github",
"gh_root": "https://github.com/bmw-software-engineering/lobster",
"commit": "main",
"file": "lobster\\tools\\python\\python.py",
"line": 89,
"exec_commit_id": "e1981245cb1c5064d42299b59f80f4e1c3c37901"
},
"name": "python.parse_value",
"messages": [],
"just_up": [],
"just_down": [],
"just_global": [],
"tracing_status": "OK",
"language": "Python",
"kind": "Function"
},
{
"tag": "python python.main",
"location": {
"kind": "github",
"gh_root": "https://github.com/bmw-software-engineering/lobster",
"commit": "main",
"file": "lobster\\tools\\python\\python.py",
"line": 451,
"exec_commit_id": "e1981245cb1c5064d42299b59f80f4e1c3c37901"
},
"name": "python.main",
"messages": [
"unknown tracing target req python_req.Dummy_Requirement"
],
"just_up": [],
"just_down": [],
"just_global": [],
"tracing_status": "MISSING",
"language": "Python",
"kind": "Function"
}
],
"coverage": 96.42857142857143
}
],
"policy": {
"code": {
"name": "code",
"kind": "implementation",
"traces": [],
"source": [
{
"file": "python.lobster",
"filters": []
}
],
"needs_tracing_up": false,
"needs_tracing_down": false,
"breakdown_requirements": []
}
},
"matrix": []
}
137 changes: 79 additions & 58 deletions tests-UI/report_test/test_html_report.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,88 @@
import sys
import importlib
import time
import json
import subprocess
import os
from datetime import datetime, timezone
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class ButtonTest:

class LobsterUIReportTests:
"""UI Automation Tests for Lobster Report."""

TESTS_UI_PATH = "tests-UI"
TIMEOUT = 10

def __init__(self):
# Add tests-UI path and import driver setup
sys.path.append('tests-UI')
sys.path.append(self.TESTS_UI_PATH)
self.driver = self._setup_driver()

def _setup_driver(self):
"""Initialize the Selenium WebDriver."""
try:
self.driver = importlib.import_module("tests-UI.setup").setup_driver()
return importlib.import_module("tests-UI.setup").setup_driver()
except ImportError as e:
sys.stderr.write(f"Error importing driver module: {e}\n")
sys.exit(1)

def test_show_issue_button(self):
"""
Test the toggle functionality of the Show Issue button.
"""
sys.stdout.write("Testing Show Issue button...\n")
"""Test the toggle functionality of the Show Issue button."""
print("Testing Show Issue button...")

for toggle in range(2):
try:
WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.ID, 'BtnToggleIssue'))
WebDriverWait(self.driver, self.TIMEOUT).until(
EC.element_to_be_clickable((By.ID, "BtnToggleIssue"))
).click()
element = self.driver.find_element(By.ID, 'issues-section')

if (toggle == 0 and element.value_of_css_property("display") == "block") or \
(toggle == 1 and element.value_of_css_property("display") == "none"):
sys.stdout.write(f"Issue items visibility is as expected.\n")
element = self.driver.find_element(By.ID, "issues-section")
expected_display = "block" if toggle == 0 else "none"

if element.value_of_css_property("display") == expected_display:
print("Issue items visibility is as expected.")
else:
sys.stderr.write(f"Test failed. Visibility mismatch.\n")
sys.stderr.write("Test failed: Visibility mismatch.\n")
return False
except Exception as e:
sys.stderr.write(f"Error during Show Issue button test: {e}\n")
return False
return True

def click_and_verify(self, button_xpath, item_class, status):
"""
Click a button and verify the visibility of elements by class.
"""
"""Click a button and verify the visibility of elements."""
try:
WebDriverWait(self.driver, 10).until(
WebDriverWait(self.driver, self.TIMEOUT).until(
EC.element_to_be_clickable((By.XPATH, button_xpath))
).click()

if item_class == "item-":
xpath = "//div[starts-with(@class, 'item-') and not(contains(@class, 'item-name'))]"
total_items = len(self.driver.find_elements(By.XPATH, xpath))
else:
WebDriverWait(self.driver, 10).until(
lambda d: len(d.find_elements(By.CLASS_NAME, item_class)) > 0
)
total_items = len(self.driver.find_elements(By.CLASS_NAME, item_class))
elements = self.driver.find_elements(By.CLASS_NAME, item_class) if item_class != "item-" else \
self.driver.find_elements(By.XPATH, "//div[starts-with(@class, 'item-') and not(contains(@class, 'item-name'))]")

sys.stdout.write(f"{total_items} items retrieved after clicking the '{status}' button.\n")
print(f"{len(elements)} items retrieved after clicking '{status}' button.")
return True
except Exception as e:
print(f"No items found for '{status}' button, skipping check.")
return False

def check_hidden_elements(self, item_classes, current_status):
"""
Verify that elements for statuses other than the current one are hidden.
"""
"""Ensure that elements for other statuses are hidden."""
for status, class_name in item_classes.items():
if status != current_status:
try:
element = self.driver.find_element(By.CLASS_NAME, class_name)
display_property = element.value_of_css_property("display")
expected_display = "none" if current_status != "Show All" else "block"

if display_property == expected_display:
sys.stdout.write(f"'{status}' items visibility is as expected.\n")
if element.value_of_css_property("display") == expected_display:
print(f"'{status}' items visibility is as expected.")
else:
sys.stderr.write(f"Visibility mismatch for '{status}' items.\n")
except Exception as e:
except Exception:
print(f"No items found for '{status}' button.")

def test_html_report_title(self):
"""
Test various buttons in an HTML report and their corresponding item visibility.
"""
"""Test visibility toggles in the HTML report."""
button_xpath = {
"OK": '//*[@id="btnFilterItem"]/button[2]',
"Missing": '//*[@id="btnFilterItem"]/button[3]',
Expand All @@ -101,28 +100,50 @@ def test_html_report_title(self):
"Show All": "item-",
}

try:
for status, xpath in button_xpath.items():
sys.stdout.write(f"Testing '{status}' button...\n")
if self.click_and_verify(xpath, item_classes[status], status):
time.sleep(1)
self.check_hidden_elements(item_classes, status)
for status, xpath in button_xpath.items():
print(f"Testing '{status}' button...")
if self.click_and_verify(xpath, item_classes[status], status):
time.sleep(1)
self.check_hidden_elements(item_classes, status)

if not self.test_show_issue_button():
sys.stderr.write("Show Issue button test failed.\n")
sys.exit(1)

if not self.test_show_issue_button():
sys.stderr.write("Show Issue button test failed.\n")
sys.exit(1)
print("All tests passed successfully.")

sys.stdout.write("All tests passed successfully.\n")
except Exception as e:
sys.stderr.write(f"Test execution error: {e}\n")
sys.exit(1)
def test_git_hash_timestamp(self):
"""Verify git commit timestamps in the report output."""
report_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "report.output")
print(f"Processing report: {report_path}")

with open(report_path) as file:
data = json.load(file)

for level in data.get("levels", []):
for item in level.get("items", []):
tag, exec_commit_id = item.get("tag"), item.get("location", {}).get("exec_commit_id")
if not (tag and exec_commit_id):
continue

elements = self.driver.find_elements(By.XPATH, "//div[starts-with(@class, 'item-') and not(contains(@class, 'item-name'))]")
for elem in elements:
text = elem.text.replace("Python Function", "python")
if tag in text and exec_commit_id in text:
result = subprocess.run(
['git', 'show', '-s', '--format=%ct', exec_commit_id],
capture_output=True, text=True, check=True
)

expected_time = datetime.fromtimestamp(int(result.stdout.strip()), tz=timezone.utc)
if str(expected_time) in text:
print("Timestamp verification passed.")

def run_tests(self):
"""
Run all the tests in sequence.
"""
"""Execute all test cases."""
try:
self.test_html_report_title()
self.test_git_hash_timestamp()
except Exception as e:
sys.stderr.write(f"Critical error during test execution: {e}\n")
sys.exit(1)
Expand All @@ -132,5 +153,5 @@ def run_tests(self):


if __name__ == "__main__":
test_suite = ButtonTest()
test_suite.run_tests()
LobsterUIReportTests().run_tests()

Loading

0 comments on commit 9daf37e

Please sign in to comment.