[](https://pypi.org/project/python-automation-framework)

[](https://app.codecov.io/github/mreiche/python-automation-framework)
# PAF - Python Automation Framework
Python implementation of [Testerra](https://github.com/telekom/testerra) API.
It is basically a wrapper for Selenium *WebDriver* and *WebElement* which brings some more comfort features.
This is not a test framework, but it implements assertion features anyway.
The basic concept is, to identify *WebElements* on every action or property accessor to prevent `StaleElementExceptions`.
## Quick start
```python
import inject
import paf.config
from paf.locator import By
from paf.page import FinderPage, PageFactory
# Configure dependency injection
inject.configure(paf.config.inject)
# Instantiate the page factory
page_factory = inject.instance(PageFactory)
# Create a simple finder page
page = page_factory.create_page(FinderPage)
# Visit URL
page.open("https://google.com")
# Find element
element = page.find("#q")
# Perform actions
element.type("Search")
# Perform assertions
element.expect.text.be("Search")
```
### Prerequisites
- You need at least a local *WebDriver* installed.
```shell
brew|choco|apt install chromedriver
```
- Python 3.10 (or higher).
## Feature list
- [UiElements](doc/uielement.md)
- [Locators](doc/locators.md)
- [Page objects](doc/pages.md)
- [Components](doc/components.md)
- [Managing WebDrivers](doc/manager.md)
- [Execution controlling](doc/control.md)
- [Inject listener](doc/listener.md)
### Missing features (tdb)
- Rect assertions
- Drag & Drop over frames
## Environment variables
* `PAF_BROWSER_SETTING=chrome:90`: Sets the requested browser name and it's version.
* `PAF_WINDOW_SIZE=1920x1080`: Sets the browsers default window size.
* `PAF_SCREENSHOTS_DIR=screenshots`: Sets the screenshots' directory.
* `PAF_SEQUENCE_WAIT_AFTER_FAIL=0.3`: Wait in seconds whenever a sequence action fails.
* `PAF_SEQUENCE_RETRY_COUNT=3`: Retry count for every sequence action.
* `PAF_DEMO_MODE=0`: Enables the demo mode by highlighting actions and assertions.
* `PAF_SELENIUM_SERVER_URL=http://127.0.0.1:4444`: Uses Selenium server if set.
* `PAF_DRIVER_PATH`: Path to Webdriver binary
* `PAF_BINARY_PATH`: Path to User agent's binary
## Examples
Some real world examples.
1. [test_google.py](examples/test_google.py): is a regular Google search, implemented with [Page Objects](doc/pages.md) and [Components](doc/components.md).
2. [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.
3. [test_asyncio.py](examples/test_asyncio.py): Parallel execution via `asyncio`.
4. [test_monkeytype.py](examples/test_monkeytype.py): Typing test on https://monkeytype.com
## Comparison
Comparison of the syntax with other frameworks.
**Pylenium**
```python
py.get("a[href='/about']").should().have_text("About")
find("a[href='/about']").expect.text.be("About")
```
**SeleniumBase**
```python
self.assert_text_not_visible("Thanks for your purchase.", "#app .success")
find("#app .success").expect.text.not_be("Thanks for your purchase.")
```
**Selene**
```python
browser.all('#rso>div').should(have.size_greater_than(5)) \
.first.should(have.text('Selenium automates browsers'))
div = find("#rso>div")
div.expect.count.greater_than(5).be(True)
div.first.expect.text.be("Selenium automates browsers")
```
References: https://www.nextgenerationautomation.com/post/python-test-automation-frameworks
## Developer area
### Testing
#### Run the tests on your local machine
```shell
PAF_TEST_HEADLESS=1 PAF_TEST_LOCAL_SELENIUM=0 pytest --cov=paf -n=4 test
```
#### Build test base container (for use in GitHub Actions)
```shell
podman build -f ubuntu-base.Dockerfile --arch=amd64 -t paf-test-base:latest
source build.env
echo $DOCKER_CONTAINER_REGISTRY_TOKEN | podman login -u mreiche --password-stdin ghcr.io
podman push paf-test-base:latest docker://ghcr.io/mreiche/paf-test-base:latest
```
#### Build test runner container (for testing)
Run tests within container
```shell
podman 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
```
#### Run local selenium server
```shell
wget https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.9.0/selenium-server-4.9.0.jar -O selenium-server.jar
java -jar selenium-server.jar standalone --host 127.0.0.1
```
### Debug XPaths in Browser's Developer Console
```javascript
xpath = "//dt[.//text()='Title:']/following-sibling::dd[1]"
snapshot = document.evaluate(xpath, document.body, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)
snapshot.snapshotItem(0).textContent
```
### Release update
1. Update version in `setup.py`
2. Package library
```shell
python setup.py sdist
```
3. Publish library
```shell
twine upload dist/python-automation-framework-[version].tar.gz
```
### References
- https://stackoverflow.com/questions/64033686/how-can-i-use-private-docker-image-in-github-actions
- https://tecadmin.net/setup-selenium-chromedriver-on-ubuntu/
- https://stackoverflow.com/questions/46052736/python-proxy-class
- https://chromedriver.chromium.org/
- Make stealth WebDriver: https://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver
Raw data
{
"_id": null,
"home_page": "https://github.com/mreiche/python-automation-framework",
"name": "python-automation-framework",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Mike Reiche",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/17/5d/b3df5ac148fa8d0abc7b6b7dcfa4e44af0203e0899e2a4bcca51d534285b/python-automation-framework-0.1.9.tar.gz",
"platform": null,
"description": "[](https://pypi.org/project/python-automation-framework)\n\n[](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- Python 3.10 (or higher).\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 listener](doc/listener.md)\n\n### Missing features (tdb)\n\n- Rect assertions\n- Drag & 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 default window size.\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>div').should(have.size_greater_than(5)) \\\n .first.should(have.text('Selenium automates browsers'))\n\ndiv = find(\"#rso>div\")\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",
"bugtrack_url": null,
"license": null,
"summary": "Automation framework for the WebDriver API",
"version": "0.1.9",
"project_urls": {
"Homepage": "https://github.com/mreiche/python-automation-framework"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "175db3df5ac148fa8d0abc7b6b7dcfa4e44af0203e0899e2a4bcca51d534285b",
"md5": "cce4e9f9c89025b638fee97fd45c84aa",
"sha256": "4044a37aa84a9a5291bbd900ba9d5c679d42bdc1b7689e85786b49a9c63e97c9"
},
"downloads": -1,
"filename": "python-automation-framework-0.1.9.tar.gz",
"has_sig": false,
"md5_digest": "cce4e9f9c89025b638fee97fd45c84aa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 26935,
"upload_time": "2024-12-14T17:14:20",
"upload_time_iso_8601": "2024-12-14T17:14:20.816346Z",
"url": "https://files.pythonhosted.org/packages/17/5d/b3df5ac148fa8d0abc7b6b7dcfa4e44af0203e0899e2a4bcca51d534285b/python-automation-framework-0.1.9.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-14 17:14:20",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mreiche",
"github_project": "python-automation-framework",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "selenium",
"specs": [
[
"==",
"4.23.1"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"7.3.1"
]
]
},
{
"name": "is_empty",
"specs": [
[
"==",
"1.0.1"
]
]
},
{
"name": "inject",
"specs": [
[
"==",
"4.3.1"
]
]
},
{
"name": "pytest-xdist",
"specs": [
[
"==",
"3.2.1"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
"==",
"4.0.0"
]
]
},
{
"name": "pytest-asyncio",
"specs": [
[
"==",
"0.21.1"
]
]
}
],
"lcname": "python-automation-framework"
}