A Python + Selenium test framework for the CivicDataSpace platform, covering both consumer and provider workflows. Provider tests include dataset creation, UseCase creation, collaborative creation, profile editing, and organization workflows. Tests are organized into smoke, functional, and mobile suites; they produce JSON/Markdown/PDF reports (with embedded screenshots) and measure coverage. A GitHub Actions workflow runs everything on each push/PR.
- Project Overview
- Prerequisites
- Installation & Setup
- Environment Variables
- Directory Structure
- Running Tests Locally
- Generating Reports Locally
- GitHub Actions CI
- Screenshots & Artifacts
- Contributing
- License
This repository implements a Page Object Model (POM)–based Selenium/pytest framework:
- POM Structure: Dedicated page classes under
pages/and separate locator files underlocators/. - Test Suites:
tests/consumersmoke/,functional/,mobile/
tests/providersmoke/,functional/,mobile/
- Logging & Waiting: Uses explicit waits (
WebDriverWait) and Python’sloggingfor detailed traceability. - Reporting:
pytest-json-reportplugin writes per-suite JSON files (report-<flow>-<type>.json).- Custom
report_generator.pycombines JSON data into a singlereport.json, produces a human‐readableTEST_REPORT.mdand a styledTEST_REPORT.pdf(with embedded failure screenshots).
- Coverage: Runs
coverage run -m pytest→coverage report→coverage html. A.coveragercexcludes CI/config scripts. - CI Pipeline: A single GitHub Actions YAML runs the entire matrix (consumer/provider × smoke/functional/mobile), merges JSON outputs, reruns under coverage, and publishes HTML, MD, and PDF artifacts.
- macOS | Linux | Windows with Python 3.9+.
- Git for version control.
- Optionally, GitHub CLI (
gh) for repo creation. - Google Chrome (or Chromium) installed.
- ChromeDriver binary (auto-managed by
webdriver-manager, or install manually). - Python packages (see below).
-
Clone the repository
git clone https://github.com/<your-username>/CivicDataSpace-test.git cd CivicDataSpace-test
-
Create a virtual environment (recommended)
python3 -m venv .venv source .venv/bin/activate # macOS/Linux # .venv\Scripts\activate # Windows PowerShell
-
Install dependencies
pip install --upgrade pip pip install -r requirements.txt
Required packages include:
pytest>=7.0.0pytest-json-report>=1.5.0selenium>=4.1.0webdriver-manager>=3.8.0coverage>=6.0reportlab>=3.6.0requests>=2.28.0
-
Create a
.envfile in the project root
Copy the sample below (replace placeholder values as needed):HOME_URL_DEV='' URL='https://civicdataspace.in/' LOCAL='True' # Provider test credentials PROV_TEST_EMAIL=your_provider_email@example.com PROV_TEST_PASSWORD=YourP@ssword # Consumer test credentials (if needed) CON_TEST_EMAIL=your_consumer_email@example.com CON_TEST_PASSWORD=YourC0nsumerP@ss # Other secrets (if any) API_KEY=abcdef1234567890The framework uses
python-dotenv(if installed) oros.getenv()to pick up base URLs and credentials.
URL: Base URL of the site (e.g.,https://civicdataspace.in/), used by all page classes.PROV_TEST_EMAIL&PROV_TEST_PASSWORD: Provider-account credentials for “provider” flows.CON_TEST_EMAIL&CON_TEST_PASSWORD: Consumer-account credentials (if/when consumer login is required).LOCAL: Set to'True'if running locally vs CI. (Optional flag to change browser options.)
Make sure to add .env to .gitignore so your secrets are never committed.
CivicDataSpace-test/
├── .github/
│ └── workflows/
│ └── test_and_report.yml # GitHub Actions CI workflow
├── assets/
│ └── logo.png # (Optional) Company logo for PDF reports
├── locators/
│ ├── consumer/
│ │ ├── dataset_locators.py
│ │ ├── sectors_locators.py
│ │ ├── usecase_locators.py
│ │ ├── publishers_locators.py
│ │ ├── publisher_detail_locators.py
│ │ └── about_locators.py
│ └── provider/
│ ├── provider_homepage_locators.py
│ ├── login_locators.py
│ ├── my_dashboard_locators.py
│ ├── org_locators.py
│ ├── create_dataset_locators.py
│ ├── create_usecase_locators.py
│ ├── collaboratives_list_page_locators.py
│ ├── create_collaborative_locators.py
│ ├── update_profile_locators.py
│ └── ... (others as needed)
├── pages/
│ ├── base_page.py # Shared BasePage with common helpers
│ ├── home_page.py # POM for homepage (consumer/provider entry)
│ ├── consumer/
│ │ ├── dataset_page.py
│ │ ├── sectors_page.py
│ │ ├── usecase_page.py
│ │ ├── publishers_page.py
│ │ ├── publisher_detail_page.py
│ │ └── about_page.py
│ └── provider/
│ ├── login_page.py
│ ├── provider_home_page.py
│ ├── my_dashboard_page.py
│ ├── organizations_page.py
│ ├── create_dataset_page.py
│ ├── create_usecase_page.py
│ ├── collaboratives_list_page.py
│ ├── create_collaborative_page.py
│ ├── update_profile_page.py
│ └── ... (others as needed)
├── screenshots/ # Auto-created: failure screenshots are captured here
│ └── ... (*.png)
├── tests/
│ ├── data/
│ │ ├── test_data.py # Test data constants (Dataset, UseCase, Collaborative, Profile)
│ │ └── sample_profile_image.png # Sample image for uploads
│ ├── consumer/
│ │ ├── smoke/
│ │ │ └── test_con_flow.py
│ │ ├── functional/
│ │ │ └── test_consumer_functional_*.py
│ │ └── mobile/
│ │ └── test_consumer_mobile_*.py
│ └── provider/
│ ├── smoke/
│ │ ├── test_prv_001_login.py
│ │ ├── test_prv_002_ind_create_dataset.py
│ │ ├── test_prv_003_ind_create_usecase.py
│ │ ├── test_prv_004_ind_add_charts.py
│ │ ├── test_prv_005_ind_edit_profile.py
│ │ ├── test_prv_006_org_create_dataset.py
│ │ ├── test_prv_007_org_create_usecase.py
│ │ ├── test_prv_008_org_add_charts.py
│ │ ├── test_prv_009_org_edit_profile.py
│ │ ├── test_prv_010_ind_create_collaborative.py
│ │ └── test_prv_011_org_create_collaborative.py
│ ├── functional/
│ │ └── ...
│ └── mobile/
│ └── test_prv_mobile_*.py
├── conftest.py # Pytest fixtures, hooks, screenshot capture, report hooks
├── pytest.ini # Pytest configuration (markers, addopts, etc.)
├── .coveragerc # Coverage.py configuration
├── report_generator.py # Reads report.json → builds TEST_REPORT.md + TEST_REPORT.pdf
├── requirements.txt # All Python dependencies
├── .env # (Ignored) Stores URL and credentials
└── README.md # ← You are here
The framework uses centralized test data classes in tests/data/test_data.py:
- DatasetTestData: Dataset creation constants (name templates, descriptions, tags, sectors, geography, licenses)
- UseCaseTestData: UseCase creation constants (name templates, descriptions, URLs, SDG goals, sectors)
- CollaborativeTestData: Collaborative creation constants (name templates, summaries, platform URLs, dates, SDG goals)
- ProfileTestData: Profile editing constants (first name, last name, bio, social links)
Each class provides:
- Static template strings for reproducible test data
- Helper methods (e.g.,
get_dataset_name(),get_use_case_name()) that generate timestamped unique values get_all_data()methods that return complete data dictionaries for form filling
This centralized approach ensures:
- Consistent test data across all test files
- Easy maintenance and updates
- Database constraint compliance (e.g., varchar limits)
- Unique identifiers for parallel test execution
All test suites rely on ChromeDriver, managed automatically by webdriver-manager or via CHROMEDRIVER_PATH environment variable. By default, tests run in headed mode unless you explicitly set headless.
The provider smoke test suite includes comprehensive end-to-end workflows:
- PRV_001: Login flow (individual user)
- PRV_002-004: Individual user workflows
- Dataset creation
- UseCase creation
- Chart/visualization addition
- PRV_005: Individual profile editing
- PRV_006-008: Organization workflows
- Dataset creation (as organization)
- UseCase creation (as organization)
- Chart/visualization addition (as organization)
- PRV_009: Organization profile editing
- PRV_010-011: Collaborative creation workflows
- Individual user collaborative creation
- Organization collaborative creation
Each test uses the Page Object Model with dedicated locators, page classes, and test data from tests/data/test_data.py.
Run only the consumer smoke tests:
pytest tests/consumer/smoke --json-report --json-report-file=report-consumer-smoke.json -qRun consumer functional tests:
pytest tests/consumer/functional --json-report --json-report-file=report-consumer-functional.json -qRun consumer mobile tests:
pytest tests/consumer/mobile --json-report --json-report-file=report-consumer-mobile.json -qRun provider smoke (login) tests:
pytest tests/provider/smoke --json-report --json-report-file=report-provider-smoke.json -qRun provider functional tests:
pytest tests/provider/functional --json-report --json-report-file=report-provider-functional.json -qRun provider mobile tests (if implemented):
pytest tests/provider/mobile --json-report --json-report-file=report-provider-mobile.json -qIf you want to run every test in one invocation (no JSON report), simply:
pytest -qThis will execute both consumer/ and provider/ suites in smoke/functional/mobile subfolders.
Each pytest ... --json-report --json-report-file=report-<flow>-<type>.json produces a JSON file in the working directory. Example:
report-consumer-smoke.json
report-provider-functional.json
report-provider-mobile.json
You can merge them manually or let report_generator.py do it.
After you have one (or more) report-*.json, merge them into a single report.json:
python << 'EOF'
import json, glob, os
merged = {"root": os.getcwd(), "tests": []}
for fname in glob.glob("report-*.json"):
data = json.load(open(fname, "r", encoding="utf-8"))
merged["tests"].extend(data.get("tests", []))
# Basic summary
total = len(merged["tests"])
passed = sum(1 for t in merged["tests"] if t.get("outcome")=="passed")
failed = sum(1 for t in merged["tests"] if t.get("outcome")=="failed")
merged["summary"] = {"
... (truncated for brevity) ...