{"id":16401766,"url":"https://github.com/mreiche/python-automation-framework","last_synced_at":"2025-03-23T05:31:11.013Z","repository":{"id":154157421,"uuid":"625886051","full_name":"mreiche/python-automation-framework","owner":"mreiche","description":"Automation Framework for Selenium WebDriver API","archived":false,"fork":false,"pushed_at":"2024-04-26T09:27:02.000Z","size":307,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-27T09:31:48.040Z","etag":null,"topics":["automation","automation-framework","selenium","test-automation","testing","webdriver"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mreiche.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-10T10:21:43.000Z","updated_at":"2024-07-18T07:48:15.724Z","dependencies_parsed_at":null,"dependency_job_id":"82061b89-4e57-45b8-bf26-1f824fd98b3d","html_url":"https://github.com/mreiche/python-automation-framework","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mreiche%2Fpython-automation-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mreiche%2Fpython-automation-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mreiche%2Fpython-automation-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mreiche%2Fpython-automation-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mreiche","download_url":"https://codeload.github.com/mreiche/python-automation-framework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245061382,"owners_count":20554563,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","automation-framework","selenium","test-automation","testing","webdriver"],"created_at":"2024-10-11T05:44:06.143Z","updated_at":"2025-03-23T05:31:11.001Z","avatar_url":"https://github.com/mreiche.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Pypi](https://img.shields.io/pypi/v/python-automation-framework.svg)](https://pypi.org/project/python-automation-framework)\n![Tests Status](https://github.com/mreiche/python-automation-framework/actions/workflows/integration-tests.yml/badge.svg)\n[![Code Coverage Status](https://codecov.io/github/mreiche/python-automation-framework/branch/main/graph/badge.svg)](https://app.codecov.io/github/mreiche/python-automation-framework)\n\n\n# PAF - Python Automation Framework\n\nPython implementation of [Testerra](https://github.com/telekom/testerra) API.\n\nIt is basically a wrapper for Selenium *WebDriver* and *WebElement* which brings some more comfort features.\nThis is not a test framework, but it implements assertion features anyway.\n\nThe basic concept is, to identify *WebElements* on every action or property accessor to prevent `StaleElementExceptions`.\n\n## Quick start\n\n```python\nimport inject\nimport paf.config\nfrom paf.locator import By\nfrom paf.page import FinderPage, PageFactory\n\n# Configure dependency injection\ninject.configure(paf.config.inject)\n\n# Instantiate the page factory\npage_factory = inject.instance(PageFactory)\n\n# Create a simple finder page\npage = page_factory.create_page(FinderPage)\n\n# Visit URL\npage.open(\"https://google.com\")\n\n# Find element\nelement = page.find(\"#q\")\n\n# Perform actions\nelement.type(\"Search\")\n\n# Perform assertions\nelement.expect.text.be(\"Search\")\n```\n\n### Prerequisites\n\n- You need at least a local *WebDriver* installed.\n   ```shell\n   brew|choco|apt install chromedriver\n   ```\n\n## Feature list\n\n- [UiElements](doc/uielement.md)\n- [Locators](doc/locators.md)\n- [Page objects](doc/pages.md)\n- [Components](doc/components.md)\n- [Managing WebDrivers](doc/manager.md)\n- [Execution controlling](doc/control.md)\n- [Inject listeners](doc/listeners.md)\n\n### Missing features (tdb)\n\n- Rect assertions\n- Drag \u0026 Drop over frames\n\n## Environment variables\n\n* `PAF_BROWSER_SETTING=chrome:90`: Sets the requested browser name and it's version.\n* `PAF_WINDOW_SIZE=1920x1080`: Sets the browsers initial window size.\n* `PAF_WINDOW_POSITION=0x0`: Place the initial window to a different location/screen.\n* `PAF_WINDOW_MAXIMIZE=False`: Maximize the initial window.\n* `PAF_SCREENSHOTS_DIR=screenshots`: Sets the screenshots' directory.\n* `PAF_SEQUENCE_WAIT_AFTER_FAIL=0.3`: Wait in seconds whenever a sequence action fails. \n* `PAF_SEQUENCE_RETRY_COUNT=3`: Retry count for every sequence action.\n* `PAF_DEMO_MODE=0`: Enables the demo mode by highlighting actions and assertions.\n* `PAF_SELENIUM_SERVER_URL=http://127.0.0.1:4444`: Uses Selenium server if set.\n* `PAF_DRIVER_PATH`: Path to Webdriver binary\n* `PAF_BINARY_PATH`: Path to User agent's binary\n\n## Examples\n\nSome real world examples.\n\n1. [test_google.py](examples/test_google.py): is a regular Google search, implemented with [Page Objects](doc/pages.md) and [Components](doc/components.md). \n2. [test_todo_mvc.py](examples/test_todo_mvc.py): are re-implemented test cases from the [Robot Framework TodoMVC](https://docs.robotframework.org/docs/examples/todo) example. It's IMHO developer friendly, better readable and less code. \n3. [test_asyncio.py](examples/test_asyncio.py): Parallel execution via `asyncio`.\n4. [test_monkeytype.py](examples/test_monkeytype.py): Typing test on https://monkeytype.com\n\n## Comparison\n\nComparison of the syntax with other frameworks.\n\n**Pylenium**\n```python\npy.get(\"a[href='/about']\").should().have_text(\"About\")\n\nfind(\"a[href='/about']\").expect.text.be(\"About\")\n```\n**SeleniumBase**\n```python\nself.assert_text_not_visible(\"Thanks for your purchase.\", \"#app .success\")\n\nfind(\"#app .success\").expect.text.not_be(\"Thanks for your purchase.\")\n```\n**Selene**\n```python\nbrowser.all('#rso\u003ediv').should(have.size_greater_than(5)) \\\n    .first.should(have.text('Selenium automates browsers'))\n\ndiv = find(\"#rso\u003ediv\")\ndiv.expect.count.greater_than(5).be(True)\ndiv.first.expect.text.be(\"Selenium automates browsers\")\n```\n\nReferences: https://www.nextgenerationautomation.com/post/python-test-automation-frameworks\n\n## Developer area\n\n### Testing\n#### Run the tests on your local machine\n```shell\nPAF_TEST_HEADLESS=1 PAF_TEST_LOCAL_SELENIUM=0 pytest --cov=paf -n=4 test\n```\n\n#### Build test base container (for use in GitHub Actions)\n```shell\npodman build -f ubuntu-base.Dockerfile --arch=amd64 -t paf-test-base:latest\nsource build.env\necho $DOCKER_CONTAINER_REGISTRY_TOKEN | podman login -u mreiche --password-stdin ghcr.io\npodman push paf-test-base:latest docker://ghcr.io/mreiche/paf-test-base:latest\n```\n\n#### Build test runner container (for testing)\nRun tests within container\n```shell\npodman run -e PAF_TEST_HEADLESS=1 -e PAF_TEST_CONTAINER=1 -e PAF_TEST_LOCAL_SELENIUM=0 paf-test-base:latest pytest --cov=paf -n=4 test\n```\n\n#### Run local selenium server\n```shell\nwget https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.9.0/selenium-server-4.9.0.jar -O selenium-server.jar\njava -jar selenium-server.jar standalone --host 127.0.0.1\n```\n\n### Debug XPaths in Browser's Developer Console\n\n```javascript\nxpath = \"//dt[.//text()='Title:']/following-sibling::dd[1]\"\nsnapshot = document.evaluate(xpath, document.body, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)\nsnapshot.snapshotItem(0).textContent\n```\n\n### Release update\n1. Update version in `setup.py`\n2. Package library\n    ```shell\n    python setup.py sdist\n    ```\n3. Publish library\n    ```shell\n    twine upload dist/python_automation_framework-[version].tar.gz\n    ```\n\n### References\n- https://stackoverflow.com/questions/64033686/how-can-i-use-private-docker-image-in-github-actions\n- https://tecadmin.net/setup-selenium-chromedriver-on-ubuntu/\n- https://stackoverflow.com/questions/46052736/python-proxy-class\n- https://chromedriver.chromium.org/\n- Make stealth WebDriver: https://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmreiche%2Fpython-automation-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmreiche%2Fpython-automation-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmreiche%2Fpython-automation-framework/lists"}