python-automation-framework


Namepython-automation-framework JSON
Version 0.1.9 PyPI version JSON
download
home_pagehttps://github.com/mreiche/python-automation-framework
SummaryAutomation framework for the WebDriver API
upload_time2024-12-14 17:14:20
maintainerNone
docs_urlNone
authorMike Reiche
requires_pythonNone
licenseNone
keywords
VCS
bugtrack_url
requirements selenium pytest is_empty inject pytest-xdist pytest-cov pytest-asyncio
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Pypi](https://img.shields.io/pypi/v/python-automation-framework.svg)](https://pypi.org/project/python-automation-framework)
![Tests Status](https://github.com/mreiche/python-automation-framework/actions/workflows/integration-tests.yml/badge.svg)
[![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)


# 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": "[![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- 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"
}
        
Elapsed time: 1.32279s