# Connect DevOps Testing Library
![pyversions](https://img.shields.io/pypi/pyversions/connect-devops-testing-library.svg) [![PyPi Status](https://img.shields.io/pypi/v/connect-devops-testing-library.svg)](https://pypi.org/project/connect-devops-testing-library/) [![Build Status](https://github.com/cloudblue/connect-devops-testing-library/actions/workflows/test.yml/badge.svg)](https://github.com/cloudblue/connect-devops-testing-library/actions/workflows/test.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=connect-devops-testing-library&metric=alert_status)](https://sonarcloud.io/dashboard?id=connect-devops-testing-library)
Testing library to ease Connect EaaS Processors development.
## Install
`Connect DevOps Testing Library` can be installed
from [pypi.org](https://pypi.org/project/connect-devops-testing-library/) using pip:
```bash
$ pip install connect-devops-testing-library
```
## Usage
DevOps Testing Library has a small request builder to ease the manipulation of the connect requests during testing:
````python
from connect.devops_testing import fixtures
import os
template = os.path.dirname(__file__) + '/request.json'
request = (fixtures.make_request_builder(template)
.with_type('purchase')
.with_asset_product('PRD-000-000-000', 'Product Name')
.with_asset_configuration_param('SOME_ASSET_CFG__PARAM_ID_A', 'some_cfg_value_a')
.with_asset_param('SOME_ASSET_PARAM_ID_001', 'some_value_001')
.with_asset_param('SOME_ASSET_PARAM_ID_002', 'some_value_002')
.build())
````
DevOps Testing Library also has several built-in assert functions that can be easily used to evaluate a connect request
response:
```python
from connect.devops_testing import asserts
asserts.request_status(request, 'approved')
asserts.asset_status(request, 'active')
asserts.asset_param_value_not_equal(request, 'SOME_ASSET_PARAM_ID_001', 'some_expected_value')
```
Using these two features you can easily create a small test to check a purchase request of your processor:
```python
from connect.devops_testing import fixtures, asserts
from my_ext.extension import MyExtension
import os
def test_should_approve_request(mocked_connect_client, mocked_service_client, logger, eaas_config):
template = os.path.dirname(__file__) + '/request.json'
# prepare the request.
request = (fixtures.make_request_builder(template)
.with_type('purchase')
.with_status('pending')
.with_asset_param('subscription_id', '')
.build())
# instantiate and execute the extension for the given request.
extension = MyExtension(mocked_connect_client, logger, eaas_config)
result = extension.process_asset_adjustment_request(request)
# evaluate the task result and request.
asserts.task_response_status(result, 'success')
asserts.request_status(request, 'approved')
asserts.asset_status(request, 'active')
asserts.asset_param_value(request, 'subscription_id', '==', 'ID:123456789')
```
Additionally, you may want to create real end-to-end test calling Connect and evaluating the processed request, for this
you should use the built-in request dispatcher. The dispatcher will take automatically the required credentials from the
environment variables in `CONNECT_API_KEY` and `CONNECT_API_URL`. Alternatively, you can pass explicitly the credentials
to the `make_request_dispatcher(api_key=XXX, api_url=YYY)` function. Let's see example:
```python
from connect.devops_testing import asserts, fixtures
import os
def test_should_approve_purchase_request_successfully():
template = os.path.dirname(__file__) + '/request.json'
# prepare the request.
request = (fixtures.make_request_builder(template)
.with_type('purchase')
.with_status('pending')
.with_asset_param('subscription_id', '')
.build())
# dispatch the request to connect and wait some time so the
# processor can process the request.
request = (fixtures.make_request_dispatcher()
.provision_request(request, 10, 20))
# evaluate the processed request.
asserts.request_status(request, 'approved')
asserts.asset_status(request, 'active')
asserts.asset_param_value(request, 'subscription_id', '==', 'ID:123456789')
```
Once the request is dispatched the Dispatcher will reload the request again every `10` seconds a maximum of `20`
attempts. If the request has not been processed the asserts may fail. The wait time between request reload can be
configured directly in the `.provision_request(timeout=10, max_attempt=20)` method call.
Obviously, some Connect processors may take a lot of time to process a request, for those type of processors this kind
of end-to-end test is not suitable.
### Behavior Driven Development
Finally, the DevOps Testing Library also allows you to easily use Behave! BDD tool for you test. You just need to set
the following code in your `features/environment.py` file
```python
from behave import use_fixture
# import the built-in steps for e2e testing.
from connect.devops_testing.bdd import steps
from connect.devops_testing.bdd.fixtures import (
use_connect_request_dispatcher,
use_connect_request_builder,
use_connect_request_store,
)
def before_all(context):
# attach the request dispatcher to the behave context.
use_fixture(
fixture_func=use_connect_request_dispatcher,
context=context,
)
# attach the request builder to the behave context.
use_fixture(
fixture_func=use_connect_request_builder,
context=context,
)
def before_feature(context, feature):
# reset the request store for each feature
use_fixture(
fixture_func=use_connect_request_store,
context=context,
reset=True
)
```
It's time to define the feature file in `features/purchase.feature`:
```gherkin
Feature: Purchase a new subscription.
Scenario: Customer buys a subscription.
Given a new valid email address
When subscription request is processed
Then the subscription id is provided
```
Now let's define the steps in `features/steps/purchase.py` file
```python
from behave import given, then
from connect.devops_testing import asserts
import os
@given("a new valid email address")
def step_impl(context):
template = os.path.dirname(__file__) + '/request.json'
context.request = (context.builder
.from_file(template)
.with_asset_param('CUSTOMER_EMAIL_ADDRESS', 'vincent.vega@gmail.com'))
@then("the subscription id is provided")
def step_impl(context):
asserts.request_status(context.request, 'approved')
asserts.asset_status(context.request, 'active')
asserts.asset_param_value_not_equal(context.request, 'CUSTOMER_EMAIL_ADDRESS', '')
```
The `@step("subscription request is processed")` is provided by the DevOps Testing Library.
Available BDD steps:
| Step | Description |
| ------------- | ------------- |
| `request is processed` | Process the request into Connect Platform. |
| `subscription request is processed` | Alias of `request is processed`. |
| `tier configuration request is processed` | Alias of `request is processed`. |
| `tier config request` | Loads a tier configuration request template. |
| `asset request` | Loads an asset request template. |
| `request with id "{request_id}"` | Sets the request id. |
| `request with status "{request_status}"` | Set the request status. |
| `request with configuration account "{account_id}"` | Set the request tier configuration account id. |
| `request with product "{product_id}"` | Set the request product id. |
| `request with marketplace "{marketplace_id}"` | Set the request marketplace id. |
| `request with reseller level "{level}"` | Set the request tier configuration reseller level. |
| `request with parameter "{parameter}" with value "{value}"` | Set a request parameter value by parameter id. |
| `request with parameter "{parameter}" value "{values}" checked` | Check a request checkbox parameter values by id. |
| `request with parameter "{parameter}" value "{values}" not checked` | Uncheck a request checkbox parameter values by id. |
| `request with parameter "{parameter}" without value` | Unset the request parameter value by id. |
| `request with parameter "{parameter}" with value error "{value}"` | Set the request parameter value error by id. |
| `request with parameter "{parameter}" without value error` | Unset the request parameter value error. |
| `request parameter "{parameter}" value is "{value}"` | Assert that the value of the given parameter by id is the expected one. |
| `request parameter "{parameter}" value contains "{value}"` | Assert that the value of the given parameter by id contains the expected value. |
| `request parameter "{parameter}" value match "{pattern}"` | Assert that the value of the given parameter by id match the expected regex expression. |
| `request parameter "{parameter}" value error is "{value_error}"` | Assert that the value error of the given parameter by id the expected one. |
| `request parameter "{parameter}" value error contains "{value_error}"` | Assert that the value error of the given parameter by id contains the expected value. |
| `request parameter "{parameter}" value error match "{pattern}"` | Assert that the value error of the given parameter by id match the expected regex expression. |
| `request status is "{request_status}"` | Assert that the status of the request is the expected one. |
## License
`Connect DevOps Testing Library` is released under
the [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
Raw data
{
"_id": null,
"home_page": "https://github.com/cloudblue/connect-devops-testing-library",
"name": "connect-devops-testing-library",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7,<4",
"maintainer_email": "",
"keywords": "connect,eaas,testing,framework",
"author": "CloudBlue LLC",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/f2/d9/9e4a8e7efb503564d063f18187b36594d8430aa9e60f897bf4296483b553/connect_devops_testing_library-25.2.tar.gz",
"platform": null,
"description": "# Connect DevOps Testing Library\n\n![pyversions](https://img.shields.io/pypi/pyversions/connect-devops-testing-library.svg) [![PyPi Status](https://img.shields.io/pypi/v/connect-devops-testing-library.svg)](https://pypi.org/project/connect-devops-testing-library/) [![Build Status](https://github.com/cloudblue/connect-devops-testing-library/actions/workflows/test.yml/badge.svg)](https://github.com/cloudblue/connect-devops-testing-library/actions/workflows/test.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=connect-devops-testing-library&metric=alert_status)](https://sonarcloud.io/dashboard?id=connect-devops-testing-library)\n\nTesting library to ease Connect EaaS Processors development.\n\n## Install\n\n`Connect DevOps Testing Library` can be installed\nfrom [pypi.org](https://pypi.org/project/connect-devops-testing-library/) using pip:\n\n```bash\n$ pip install connect-devops-testing-library\n```\n\n## Usage\n\nDevOps Testing Library has a small request builder to ease the manipulation of the connect requests during testing:\n\n````python\nfrom connect.devops_testing import fixtures\nimport os\n\ntemplate = os.path.dirname(__file__) + '/request.json'\n\nrequest = (fixtures.make_request_builder(template)\n .with_type('purchase')\n .with_asset_product('PRD-000-000-000', 'Product Name')\n .with_asset_configuration_param('SOME_ASSET_CFG__PARAM_ID_A', 'some_cfg_value_a')\n .with_asset_param('SOME_ASSET_PARAM_ID_001', 'some_value_001')\n .with_asset_param('SOME_ASSET_PARAM_ID_002', 'some_value_002')\n .build())\n````\n\nDevOps Testing Library also has several built-in assert functions that can be easily used to evaluate a connect request\nresponse:\n\n```python\nfrom connect.devops_testing import asserts\n\nasserts.request_status(request, 'approved')\nasserts.asset_status(request, 'active')\nasserts.asset_param_value_not_equal(request, 'SOME_ASSET_PARAM_ID_001', 'some_expected_value')\n```\n\nUsing these two features you can easily create a small test to check a purchase request of your processor:\n\n```python\nfrom connect.devops_testing import fixtures, asserts\nfrom my_ext.extension import MyExtension\nimport os\n\n\ndef test_should_approve_request(mocked_connect_client, mocked_service_client, logger, eaas_config):\n template = os.path.dirname(__file__) + '/request.json'\n\n # prepare the request.\n request = (fixtures.make_request_builder(template)\n .with_type('purchase')\n .with_status('pending')\n .with_asset_param('subscription_id', '')\n .build())\n\n # instantiate and execute the extension for the given request.\n extension = MyExtension(mocked_connect_client, logger, eaas_config)\n result = extension.process_asset_adjustment_request(request)\n\n # evaluate the task result and request.\n asserts.task_response_status(result, 'success')\n asserts.request_status(request, 'approved')\n asserts.asset_status(request, 'active')\n asserts.asset_param_value(request, 'subscription_id', '==', 'ID:123456789')\n```\n\nAdditionally, you may want to create real end-to-end test calling Connect and evaluating the processed request, for this\nyou should use the built-in request dispatcher. The dispatcher will take automatically the required credentials from the\nenvironment variables in `CONNECT_API_KEY` and `CONNECT_API_URL`. Alternatively, you can pass explicitly the credentials\nto the `make_request_dispatcher(api_key=XXX, api_url=YYY)` function. Let's see example:\n\n```python\nfrom connect.devops_testing import asserts, fixtures\nimport os\n\n\ndef test_should_approve_purchase_request_successfully():\n template = os.path.dirname(__file__) + '/request.json'\n\n # prepare the request.\n request = (fixtures.make_request_builder(template)\n .with_type('purchase')\n .with_status('pending')\n .with_asset_param('subscription_id', '')\n .build())\n\n # dispatch the request to connect and wait some time so the \n # processor can process the request.\n request = (fixtures.make_request_dispatcher()\n .provision_request(request, 10, 20))\n\n # evaluate the processed request.\n asserts.request_status(request, 'approved')\n asserts.asset_status(request, 'active')\n asserts.asset_param_value(request, 'subscription_id', '==', 'ID:123456789')\n```\n\nOnce the request is dispatched the Dispatcher will reload the request again every `10` seconds a maximum of `20`\nattempts. If the request has not been processed the asserts may fail. The wait time between request reload can be\nconfigured directly in the `.provision_request(timeout=10, max_attempt=20)` method call.\n\nObviously, some Connect processors may take a lot of time to process a request, for those type of processors this kind\nof end-to-end test is not suitable.\n\n### Behavior Driven Development\n\nFinally, the DevOps Testing Library also allows you to easily use Behave! BDD tool for you test. You just need to set\nthe following code in your `features/environment.py` file\n\n```python\nfrom behave import use_fixture\n\n# import the built-in steps for e2e testing. \nfrom connect.devops_testing.bdd import steps\nfrom connect.devops_testing.bdd.fixtures import (\n use_connect_request_dispatcher,\n use_connect_request_builder,\n use_connect_request_store,\n)\n\n\ndef before_all(context):\n # attach the request dispatcher to the behave context.\n use_fixture(\n fixture_func=use_connect_request_dispatcher,\n context=context,\n )\n # attach the request builder to the behave context.\n use_fixture(\n fixture_func=use_connect_request_builder,\n context=context,\n )\n\n\ndef before_feature(context, feature):\n # reset the request store for each feature\n use_fixture(\n fixture_func=use_connect_request_store,\n context=context,\n reset=True\n )\n\n```\n\nIt's time to define the feature file in `features/purchase.feature`:\n\n```gherkin\nFeature: Purchase a new subscription.\n\n Scenario: Customer buys a subscription.\n Given a new valid email address\n When subscription request is processed\n Then the subscription id is provided\n```\n\nNow let's define the steps in `features/steps/purchase.py` file\n\n```python\nfrom behave import given, then\nfrom connect.devops_testing import asserts\nimport os\n\n\n@given(\"a new valid email address\")\ndef step_impl(context):\n template = os.path.dirname(__file__) + '/request.json'\n\n context.request = (context.builder\n .from_file(template)\n .with_asset_param('CUSTOMER_EMAIL_ADDRESS', 'vincent.vega@gmail.com'))\n\n\n@then(\"the subscription id is provided\")\ndef step_impl(context):\n asserts.request_status(context.request, 'approved')\n asserts.asset_status(context.request, 'active')\n asserts.asset_param_value_not_equal(context.request, 'CUSTOMER_EMAIL_ADDRESS', '')\n```\n\nThe `@step(\"subscription request is processed\")` is provided by the DevOps Testing Library.\n\nAvailable BDD steps:\n\n| Step | Description |\n| ------------- | ------------- |\n| `request is processed` | Process the request into Connect Platform. |\n| `subscription request is processed` | Alias of `request is processed`. |\n| `tier configuration request is processed` | Alias of `request is processed`. |\n| `tier config request` | Loads a tier configuration request template. |\n| `asset request` | Loads an asset request template. |\n| `request with id \"{request_id}\"` | Sets the request id. |\n| `request with status \"{request_status}\"` | Set the request status. |\n| `request with configuration account \"{account_id}\"` | Set the request tier configuration account id. |\n| `request with product \"{product_id}\"` | Set the request product id. |\n| `request with marketplace \"{marketplace_id}\"` | Set the request marketplace id. |\n| `request with reseller level \"{level}\"` | Set the request tier configuration reseller level. |\n| `request with parameter \"{parameter}\" with value \"{value}\"` | Set a request parameter value by parameter id. |\n| `request with parameter \"{parameter}\" value \"{values}\" checked` | Check a request checkbox parameter values by id. |\n| `request with parameter \"{parameter}\" value \"{values}\" not checked` | Uncheck a request checkbox parameter values by id. |\n| `request with parameter \"{parameter}\" without value` | Unset the request parameter value by id. |\n| `request with parameter \"{parameter}\" with value error \"{value}\"` | Set the request parameter value error by id. |\n| `request with parameter \"{parameter}\" without value error` | Unset the request parameter value error. |\n| `request parameter \"{parameter}\" value is \"{value}\"` | Assert that the value of the given parameter by id is the expected one. |\n| `request parameter \"{parameter}\" value contains \"{value}\"` | Assert that the value of the given parameter by id contains the expected value. |\n| `request parameter \"{parameter}\" value match \"{pattern}\"` | Assert that the value of the given parameter by id match the expected regex expression. |\n| `request parameter \"{parameter}\" value error is \"{value_error}\"` | Assert that the value error of the given parameter by id the expected one. |\n| `request parameter \"{parameter}\" value error contains \"{value_error}\"` | Assert that the value error of the given parameter by id contains the expected value. |\n| `request parameter \"{parameter}\" value error match \"{pattern}\"` | Assert that the value error of the given parameter by id match the expected regex expression. |\n| `request status is \"{request_status}\"` | Assert that the status of the request is the expected one. |\n\n## License\n\n`Connect DevOps Testing Library` is released under\nthe [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Testing framework to ease Connect EaaS Processors development.",
"version": "25.2",
"split_keywords": [
"connect",
"eaas",
"testing",
"framework"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3f6421f60ac146055da32d59748fd5ca4c915e8b45f6ea7df6858c810cea0a76",
"md5": "55a8d574ab1f39659f778641e7ce9b5d",
"sha256": "b63a1d7f958b0ca4d8fbfe540afd06aa160229a87b9acf3c9b6a3fe2968d432f"
},
"downloads": -1,
"filename": "connect_devops_testing_library-25.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "55a8d574ab1f39659f778641e7ce9b5d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7,<4",
"size": 19223,
"upload_time": "2023-04-03T07:58:08",
"upload_time_iso_8601": "2023-04-03T07:58:08.632140Z",
"url": "https://files.pythonhosted.org/packages/3f/64/21f60ac146055da32d59748fd5ca4c915e8b45f6ea7df6858c810cea0a76/connect_devops_testing_library-25.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f2d99e4a8e7efb503564d063f18187b36594d8430aa9e60f897bf4296483b553",
"md5": "45e9e2972c5ef84c5420e613b7332741",
"sha256": "53118db5dee658c00bf3071e081ecd9dc3df217cf7fd29488e4dcf991ffa8a6b"
},
"downloads": -1,
"filename": "connect_devops_testing_library-25.2.tar.gz",
"has_sig": false,
"md5_digest": "45e9e2972c5ef84c5420e613b7332741",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7,<4",
"size": 19307,
"upload_time": "2023-04-03T07:58:09",
"upload_time_iso_8601": "2023-04-03T07:58:09.818825Z",
"url": "https://files.pythonhosted.org/packages/f2/d9/9e4a8e7efb503564d063f18187b36594d8430aa9e60f897bf4296483b553/connect_devops_testing_library-25.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-03 07:58:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "cloudblue",
"github_project": "connect-devops-testing-library",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "connect-devops-testing-library"
}