robotframework-gevent


Namerobotframework-gevent JSON
Version 0.7.0 PyPI version JSON
download
home_pagehttps://github.com/eldaduzman/robotframework-gevent
SummaryRun keywords asynchronously with the power of gevent
upload_time2023-12-14 20:28:41
maintainer
docs_urlNone
authorEldad Uzman
requires_python>=3.8,<4.0
licenseMIT
keywords robotframework rpa automation asynchronous
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # robotframework-gevent
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Run keywords asynchronously with the power of gevent


[![Version](https://img.shields.io/pypi/v/robotframework-gevent.svg)](https://pypi.python.org/pypi/robotframework-gevent)
![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/coverage-badge.svg)
![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/pylint.svg)
![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/mutscore.svg)

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)


## installation:
```bash
pip install robotframework-gevent
```

## Usage:

```robotframework
# simple-test.robot
*** Settings ***

Library             Collections
Library             String
Library             GeventLibrary
Library             RequestsLibrary


*** Test Cases ***
Test1
    [Documentation]    Simple test flow with gevent greenlets
    Log    Hello World
    Create Gevent Bundle    alias=alias1  # Create a bundle of coroutines
    Sleep    10s    alias=alias1    # run your synchronous keyword
    # register all your keywords as coroutines to the gevent bundle
    Add Coroutine    Sleep Wrapper    alias=alias1
    Add Coroutine    Sleep    20s    alias=alias1
    Add Coroutine    Sleep    10s    alias=alias1
    Add Coroutine    GET    https://jsonplaceholder.typicode.com/posts/1    alias=alias1
    Add Coroutine    Convert To Lower Case    UPPER

    # Run your coroutines and get the values by order
    ${values}    Run Coroutines    alias=alias1
    Log Many    @{values}

    # The 3rd coroutine was a request, take it's value
    ${jsonplaceholder_resp}    Get From List    ${values}    3

    # assert the returned response code to be 200
    Status Should Be    200    ${jsonplaceholder_resp}
    # assert that the returned `userId` field equals to 1
    Should Be Equal As Strings    1    ${jsonplaceholder_resp.json()['userId']}


*** Keywords ***
Sleep Wrapper
    Sleep    1s

```


See -  [Keyword Documentation](https://eldaduzman.github.io/robotframework-gevent/GeventLibrary.html)
### run test:
```
>>> robot simple-test.robot
```
### Possible result

After test is completed go to `log.html`:

![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/images/Possible-Log-File.png)


Owing to the fact that keywords are executed asynchronously, we cannot know the order of keyword execution, so instead they are printed in a table format


### For more examples

go to [examples](https://github.com/eldaduzman/robotframework-gevent/tree/main/examples)
## Motivation

Modern software architecture is `event driven`, with many background process.
Servers are being more pro-active instead of re-active as we see in a `client server` architecture.

In order to test such systems, we need the ability to run coroutines in our test scripts.

With the power of [gevent](http://www.gevent.org/), we can run several coroutines in greenlets, so integrating them into our robotframework test script will provide super powers to our testing efforts!

## Why gevent?

Concurrency can be achieved in 3 different ways:

1.  Multiprocessing - running each task in it's own `process`.
    The cons of such an approach would be massive consumption of resources, namely CPU and memory, as this means to allocate an entire `memory heap` to each task.
    Another problem is a possible need for `Inter-Process Communication (IPC)` that might be costly.

2.  Multithreading - running each task in a `thread`.
    Unlike multiprocessing, now all tasks run on the same memory heap and separated by threads, which the CPU coordinates using `round-robin`.
    However, python's  `Global Interpreter Lock` (GIL) prevents these threads from acting concurrently, it might perform context switching when IO operation occurs but there's no control for that.


3.  Asynchronous IO - running all tasks on a single thread, while IO operations won't block the progress of the program, while code execution is committed by an   `event loop` that `selects` between attached `coroutines`.
    This is highly efficient in resources consumption when compared to multithreading and multiprocessing, but it requires some modifications to the original code.
    `Blocking` IO statements can hog the event loop and the code will not be concurrent.
    `gevent` allows programmers to write seemingly regular "blocking" python code, but it will enforce asynchronous IO compliance by `monkey patching`

## File structure
```

|   LICENSE
|   .gitignore
|   .pylintrc
|   pyproject.toml
|   poetry.lock
|   README.md

|           
+---src
|   \---GeventLibrary
|       |   \---exceptions
|       |       |   __init__.py
|       |   \---keywords
|       |       |   __init__.py
|       |       |   gevent_keywords.py
|       |   __init__.py
|       |   gevent_library.py
|               
+---atests
|   |   __init__.robot
|   |   simple-test.robot
|   |   
|   \---utests
|       |   __init__.py
|       |   test_bundle_creation.py

```
## Code styling
### `black` used for auto-formatting code [read](https://pypi.org/project/black/),
### `pylint` used for code linting and pep8 compliance [read](https://pypi.org/project/pylint/),
### `mypy` used for type hinting [read](https://pypi.org/project/mypy/),
### `robocop` static code analyzer for robotframework [read](https://pypi.org/project/robotframework-robocop/),
### `perflint` pylint extension for performance linting [read](https://betterprogramming.pub/use-perflint-a-performance-linter-for-python-eae8e54f1e99)
### `cosmic-ray` Python tool for mutation testing [read](https://python.plainenglish.io/python-mutation-testing-with-cosmic-ray-4b78eb9e0676)

## links
1. [Robotframework](https://robotframework.org/)
2. [gevent](http://www.gevent.org/)
## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
  <tbody>
    <tr>
      <td align="center"><a href="https://github.com/MalikMlitat"><img src="https://avatars.githubusercontent.com/u/19836100?v=4?s=100" width="100px;" alt="MalikMlitat"/><br /><sub><b>MalikMlitat</b></sub></a><br /><a href="https://github.com/eldaduzman/robotframework-gevent/commits?author=MalikMlitat" title="Documentation">📖</a></td>
    </tr>
  </tbody>
</table>

<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/eldaduzman/robotframework-gevent",
    "name": "robotframework-gevent",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8,<4.0",
    "maintainer_email": "",
    "keywords": "robotframework,rpa,automation,asynchronous",
    "author": "Eldad Uzman",
    "author_email": "eldadu1985@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/f9/8c/c1373c03c7528774bd29bfddd4118b4215fa023ed44dff0c445a9ce35101/robotframework_gevent-0.7.0.tar.gz",
    "platform": null,
    "description": "# robotframework-gevent\n<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->\n[![All Contributors](https://img.shields.io/badge/all_contributors-1-orange.svg?style=flat-square)](#contributors-)\n<!-- ALL-CONTRIBUTORS-BADGE:END -->\nRun keywords asynchronously with the power of gevent\n\n\n[![Version](https://img.shields.io/pypi/v/robotframework-gevent.svg)](https://pypi.python.org/pypi/robotframework-gevent)\n![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/coverage-badge.svg)\n![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/pylint.svg)\n![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/badges/mutscore.svg)\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\n## installation:\n```bash\npip install robotframework-gevent\n```\n\n## Usage:\n\n```robotframework\n# simple-test.robot\n*** Settings ***\n\nLibrary             Collections\nLibrary             String\nLibrary             GeventLibrary\nLibrary             RequestsLibrary\n\n\n*** Test Cases ***\nTest1\n    [Documentation]    Simple test flow with gevent greenlets\n    Log    Hello World\n    Create Gevent Bundle    alias=alias1  # Create a bundle of coroutines\n    Sleep    10s    alias=alias1    # run your synchronous keyword\n    # register all your keywords as coroutines to the gevent bundle\n    Add Coroutine    Sleep Wrapper    alias=alias1\n    Add Coroutine    Sleep    20s    alias=alias1\n    Add Coroutine    Sleep    10s    alias=alias1\n    Add Coroutine    GET    https://jsonplaceholder.typicode.com/posts/1    alias=alias1\n    Add Coroutine    Convert To Lower Case    UPPER\n\n    # Run your coroutines and get the values by order\n    ${values}    Run Coroutines    alias=alias1\n    Log Many    @{values}\n\n    # The 3rd coroutine was a request, take it's value\n    ${jsonplaceholder_resp}    Get From List    ${values}    3\n\n    # assert the returned response code to be 200\n    Status Should Be    200    ${jsonplaceholder_resp}\n    # assert that the returned `userId` field equals to 1\n    Should Be Equal As Strings    1    ${jsonplaceholder_resp.json()['userId']}\n\n\n*** Keywords ***\nSleep Wrapper\n    Sleep    1s\n\n```\n\n\nSee -  [Keyword Documentation](https://eldaduzman.github.io/robotframework-gevent/GeventLibrary.html)\n### run test:\n```\n>>> robot simple-test.robot\n```\n### Possible result\n\nAfter test is completed go to `log.html`:\n\n![](https://raw.githubusercontent.com/eldaduzman/robotframework-gevent/main/docs/images/Possible-Log-File.png)\n\n\nOwing to the fact that keywords are executed asynchronously, we cannot know the order of keyword execution, so instead they are printed in a table format\n\n\n### For more examples\n\ngo to [examples](https://github.com/eldaduzman/robotframework-gevent/tree/main/examples)\n## Motivation\n\nModern software architecture is `event driven`, with many background process.\nServers are being more pro-active instead of re-active as we see in a `client server` architecture.\n\nIn order to test such systems, we need the ability to run coroutines in our test scripts.\n\nWith the power of [gevent](http://www.gevent.org/), we can run several coroutines in greenlets, so integrating them into our robotframework test script will provide super powers to our testing efforts!\n\n## Why gevent?\n\nConcurrency can be achieved in 3 different ways:\n\n1.  Multiprocessing - running each task in it's own `process`.\n    The cons of such an approach would be massive consumption of resources, namely CPU and memory, as this means to allocate an entire `memory heap` to each task.\n    Another problem is a possible need for `Inter-Process Communication (IPC)` that might be costly.\n\n2.  Multithreading - running each task in a `thread`.\n    Unlike multiprocessing, now all tasks run on the same memory heap and separated by threads, which the CPU coordinates using `round-robin`.\n    However, python's  `Global Interpreter Lock` (GIL) prevents these threads from acting concurrently, it might perform context switching when IO operation occurs but there's no control for that.\n\n\n3.  Asynchronous IO - running all tasks on a single thread, while IO operations won't block the progress of the program, while code execution is committed by an   `event loop` that `selects` between attached `coroutines`.\n    This is highly efficient in resources consumption when compared to multithreading and multiprocessing, but it requires some modifications to the original code.\n    `Blocking` IO statements can hog the event loop and the code will not be concurrent.\n    `gevent` allows programmers to write seemingly regular \"blocking\" python code, but it will enforce asynchronous IO compliance by `monkey patching`\n\n## File structure\n```\n\n|   LICENSE\n|   .gitignore\n|   .pylintrc\n|   pyproject.toml\n|   poetry.lock\n|   README.md\n\n|           \n+---src\n|   \\---GeventLibrary\n|       |   \\---exceptions\n|       |       |   __init__.py\n|       |   \\---keywords\n|       |       |   __init__.py\n|       |       |   gevent_keywords.py\n|       |   __init__.py\n|       |   gevent_library.py\n|               \n+---atests\n|   |   __init__.robot\n|   |   simple-test.robot\n|   |   \n|   \\---utests\n|       |   __init__.py\n|       |   test_bundle_creation.py\n\n```\n## Code styling\n### `black` used for auto-formatting code [read](https://pypi.org/project/black/),\n### `pylint` used for code linting and pep8 compliance [read](https://pypi.org/project/pylint/),\n### `mypy` used for type hinting [read](https://pypi.org/project/mypy/),\n### `robocop` static code analyzer for robotframework [read](https://pypi.org/project/robotframework-robocop/),\n### `perflint` pylint extension for performance linting [read](https://betterprogramming.pub/use-perflint-a-performance-linter-for-python-eae8e54f1e99)\n### `cosmic-ray` Python tool for mutation testing [read](https://python.plainenglish.io/python-mutation-testing-with-cosmic-ray-4b78eb9e0676)\n\n## links\n1. [Robotframework](https://robotframework.org/)\n2. [gevent](http://www.gevent.org/)\n## Contributors \u2728\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\"><a href=\"https://github.com/MalikMlitat\"><img src=\"https://avatars.githubusercontent.com/u/19836100?v=4?s=100\" width=\"100px;\" alt=\"MalikMlitat\"/><br /><sub><b>MalikMlitat</b></sub></a><br /><a href=\"https://github.com/eldaduzman/robotframework-gevent/commits?author=MalikMlitat\" title=\"Documentation\">\ud83d\udcd6</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Run keywords asynchronously with the power of gevent",
    "version": "0.7.0",
    "project_urls": {
        "Homepage": "https://github.com/eldaduzman/robotframework-gevent",
        "Repository": "https://github.com/eldaduzman/robotframework-gevent"
    },
    "split_keywords": [
        "robotframework",
        "rpa",
        "automation",
        "asynchronous"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f98cc1373c03c7528774bd29bfddd4118b4215fa023ed44dff0c445a9ce35101",
                "md5": "ca410cc2872094710bfc85d4ad760b26",
                "sha256": "33e6675d22109aa8e8eddb71fa31335c2d84577fcdc8ba8d8797233130b16eaf"
            },
            "downloads": -1,
            "filename": "robotframework_gevent-0.7.0.tar.gz",
            "has_sig": false,
            "md5_digest": "ca410cc2872094710bfc85d4ad760b26",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8,<4.0",
            "size": 10058,
            "upload_time": "2023-12-14T20:28:41",
            "upload_time_iso_8601": "2023-12-14T20:28:41.551408Z",
            "url": "https://files.pythonhosted.org/packages/f9/8c/c1373c03c7528774bd29bfddd4118b4215fa023ed44dff0c445a9ce35101/robotframework_gevent-0.7.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-14 20:28:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "eldaduzman",
    "github_project": "robotframework-gevent",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "robotframework-gevent"
}
        
Elapsed time: 0.15700s