summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-04-11 17:49:58 +0000
committerCoprDistGit <infra@openeuler.org>2023-04-11 17:49:58 +0000
commit2be683c7765c2ad7e2eb54e971ae8d77b3c5295c (patch)
treeb8baae0baed84038f7925bbbccdcdb8c06356ba8
parent1cf5473cb59d217b8068af0568e44f8678bb8552 (diff)
automatic import of python-apiritif
-rw-r--r--.gitignore1
-rw-r--r--python-apiritif.spec997
-rw-r--r--sources1
3 files changed, 999 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..4f8dfa1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/apiritif-1.1.3.tar.gz
diff --git a/python-apiritif.spec b/python-apiritif.spec
new file mode 100644
index 0000000..399b3cd
--- /dev/null
+++ b/python-apiritif.spec
@@ -0,0 +1,997 @@
+%global _empty_manifest_terminate_build 0
+Name: python-apiritif
+Version: 1.1.3
+Release: 1
+Summary: Python framework for API testing
+License: Apache 2.0
+URL: https://github.com/Blazemeter/apiritif
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/3f/49/1b639130c415badb18aa4cceb9f6ae0af80c7c528b247cc2542b9b746838/apiritif-1.1.3.tar.gz
+BuildArch: noarch
+
+Requires: python3-nose2
+Requires: python3-pytest
+Requires: python3-requests
+Requires: python3-jsonpath-ng
+Requires: python3-lxml
+Requires: python3-unicodecsv
+Requires: python3-cssselect
+Requires: python3-chardet
+Requires: python3-pyopenssl
+Requires: python3-codecov
+
+%description
+# Apiritif
+
+Apiritif is a number of utilities aimed to simplify the process of maintaining API tests.
+Apiritif tests fully based on python nose tests. This library can help you to develop and run your existing tests.
+In order to create any valid tests for Apiritif you can read [nose test documentation](https://nose.readthedocs.io/en/latest/testing.html).
+
+Check Apiritif version with the following command:
+```
+python -m apiritif -- version
+```
+
+Here described some features of Apiritif which can help you to create tests more easily.
+
+## Overview
+
+## HTTP Requests
+
+Apiritif allows to use simple `requests`-like API for making HTTP requests.
+
+```python
+from apiritif import http
+
+response = http.get("http://example.com")
+response.assert_ok() # will raise AssertionError if request wasn't successful
+```
+
+`http` object provides the following methods:
+```python
+from apiritif import http
+
+http.get("http://api.example.com/posts")
+http.post("http://api.example.com/posts")
+http.put("http://api.example.com/posts/1")
+http.patch("http://api.example.com/posts/1")
+http.delete("http://api.example.com/posts/1")
+http.head("http://api.example.com/posts")
+```
+
+All methods (`get`, `post`, `put`, `patch`, `delete`, `head`) support the following arguments:
+```python
+def get(address, # URL for the request
+ params=None, # URL params dict
+ headers=None, # HTTP headers
+ cookies=None, # request cookies
+ data=None, # raw request data
+ json=None, # attach JSON object as request body
+ encrypted_cert=None, # certificate to use with request
+ allow_redirects=True, # automatically follow HTTP redirects
+ timeout=30) # request timeout, by default it's 30 seconds
+```
+
+##### Certificate usage
+Currently `http` supports `pem` and `pkcs12` certificates.
+Here is an example of certificate usage:
+```python
+http.get("http://api.example.com/posts", encrypted_cert=('./cert.pem', 'passphrase'))
+```
+First parameter is path to certificate, second is the passphrase certificate encrypted with.
+
+## HTTP Targets
+
+Target is an object that captures resource name of the URL (protocol, domain, port)
+and allows to set some settings applied to all requests made for a target.
+
+
+```python
+from apiritif import http
+
+qa_env = http.target("http://192.160.0.2")
+qa_env.get("/api/v4/user")
+qa_env.get("/api/v4/user")
+```
+
+Target constructor supports the following options:
+```python
+target = apiritif.http.target(
+ address, # target base address
+ base_path=None, # base path prepended to all paths (e.g. '/api/v2')
+ use_cookies=True, # use cookies
+ additional_headers=None, # additional headers for all requests
+ keep_alive=True, # reuse opened HTTP connection
+ auto_assert_ok=True, # automatically invoke 'assert_ok' after each request
+)
+```
+
+
+## Assertions
+
+Apiritif responses provide a lot of useful assertions that can be used on responses.
+
+Here's the list of assertions that can be used:
+```python
+response = http.get("http://example.com/")
+
+# assert that request succeeded (status code is 2xx or 3xx)
+response.assert_ok()
+# assert that request has failed
+response.assert_failed()
+
+# status code based assertions
+response.assert_2xx()
+response.assert_3xx()
+response.assert_4xx()
+response.assert_5xx()
+response.assert_status_code(code)
+response.assert_not_status_code(code)
+response.assert_status_code_in(codes)
+
+# content-based assertions
+
+# assert that response body contains a string
+response.assert_in_body(member)
+
+# assert that response body doesn't contain a string
+response.assert_not_in_body(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_body(regex, match=False)
+response.assert_regex_not_in_body(regex, match=False)
+
+# assert that response has header
+response.assert_has_header(header)
+
+# assert that response has header with given value
+response.assert_header_value(header, value)
+
+# assert that response's headers contains a string
+response.assert_in_headers(member)
+response.assert_not_in_headers(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_headers(member)
+response.assert_regex_not_in_headers(member)
+
+# assert that response body matches JSONPath query
+response.assert_jsonpath(jsonpath_query, expected_value=None)
+response.assert_not_jsonpath(jsonpath_query)
+
+# assert that response body matches XPath query
+response.assert_xpath(xpath_query, parser_type='html', validate=False)
+response.assert_not_xpath(xpath_query, parser_type='html', validate=False)
+
+# assert that HTML response body contains CSS selector item
+response.assert_cssselect(selector, expected_value=None, attribute=None)
+response.assert_not_cssselect(selector, expected_value=None, attribute=None)
+
+```
+
+Note that assertions can be chained, so the following construction is entirely valid:
+```python
+
+response = http.get("http://example.com/")
+response.assert_ok().assert_in_body("Example")
+```
+
+## Transactions
+
+Apiritif allows to group multiple requests or actions into a transaction using a `transaction` context manager.
+For example when we have test action like bellow we want to execute requests according to concrete user as a separate piece.
+Also we want to process test for `users/all` page even if something wrong with previous actions.
+
+```python
+def test_with_login():
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+
+Here where we can use transaction in order to wrap login process in one block.
+
+```python
+def test_with_login():
+ with apiritif.transaction('Login'):
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+At the same time requests to `users/all` page will be executed outside of transaction even if something inside transaction fails.
+
+Transaction defines the name for the block of code. This name with execution results of this particular block will be displayed in the output report.
+
+#### Smart transactions
+
+`smart_transaction` is advanced option for test flow control (stop or continue after failed test method).
+Let see another test method example:
+
+```python
+class Tests(TestCase):
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+In this case we have multiple requests divided into blocks. I do not want to test pages under `users` space if it is not available.
+For this purpose we can use `smart_transaction`.
+
+```python
+class Tests(TestCase):
+ def setUp(self):
+ apiritif.put_into_thread_store(func_mode=True)
+
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+
+ with apiritif.smart_transaction('Availability check'):
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ with apiritif.smart_transaction('Test users pages'):
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+Now this two blocks are wrapped into `smart_transaction` which would help with error test flow handling and logging.
+
+Also each transaction defines the name for the block of code and will be displayed in the output report.
+
+Now about `apiritif.put_into_thread_store(func_mode=True)`, this is test execution mode for apiritif.
+We can execute all of the transactions in test no matter what or stop after first failed transaction.
+This flag tells to apiritif "Stop execution if some transaction failed". `False` says "Run till the end in any case".
+
+##### Nose Flow Control
+It's one more feature based on smart transactions. It changes `func_mode` if necessary to execute whole teardown block,
+intended to finalize all necessary things.
+
+```python
+def test_flow-control(self):
+ try:
+ self._method_with_exception()
+ self._skipped_method()
+ finally:
+ apiritif.set_stage("teardown")
+ self._teardown1()
+ self._teardown2()
+```
+If this test will be interrupted in `_method_with_exception`, both of teardown methods will be executed even if them raise exception.
+Please note two differences with usage of `tearDown` method of nose:
+1. all parts of teardown stage will be executed as mentioned above (will be interrupted in regular nose execution)
+2. results of teardown steps will be written by apiritif SampleWriter into output file (nose lost them as tearDown isn't recognised as test).
+
+##### Graceful shutdown
+Somethimes waiting of end of test isn't necessary and we prefer to break it but save all current results and handle all teardown steps. (see above)
+It's possible with GRACEFUL flag. To use it you can run apiritif with GRACEFUL environment variable pointed to any file name.
+Apiritif will be interrupted as soon as the file is created.
+
+## CSV Reader
+In order to use data from csv file as test parameters Apiritif provides two different csv readers.
+Simple `CSVReader` helps you to read data from file line by line and use this data wherever you need:
+
+```python
+data_reader = apiritif.CSVReader('---path to required file---')
+class Tests(TestCase):
+ def test_user_page():
+ data_reader.read_vars()
+ vars = data_reader.get_vars()
+ http.get("https://blazedemo.com/users/" + vars.user_id).assert_ok()
+```
+
+In case of multithreading testing you may need to deviate data between threads and ysu uniq lines for each thread.
+`CSVReaderPerThread` helps to solve this problem:
+
+```python
+data_per_thread_reader = apiritif.CSVReaderPerThread('---path to required file---')
+class Tests(TestCase):
+ def setUp(self):
+ data_per_thread_reader.read_vars()
+ self.vars = data_per_thread_reader.get_vars()
+
+ def test_user_page():
+ http.get("https://blazedemo.com/users/" + self.vars.user_id).assert_ok()
+```
+
+## Execution results
+
+Apiritif writes output data from tests in `apiritif.#.csv` files by default. Here `#` is number of executing process.
+The output file is similar to this:
+```csv
+timeStamp,elapsed,Latency,label,responseCode,responseMessage,success,allThreads,bytes
+1602759519185,0,0,Correct test,,,true,0,2
+1602759519186,0,0,Correct transaction,,,true,0,2
+1602759519187,0,0,Test with exception,,Exception: Horrible error,false,0,2
+```
+It contains test and transaction results for executed tests by one process.
+
+### Environment Variables
+
+There are environment variables to control length of response/request body to be written into traces and logs:
+ * `APIRITIF_TRACE_BODY_EXCLIMIT` - limit of body part to include into exception messages, default is 1024
+ * `APIRITIF_TRACE_BODY_HARDLIMIT` - limit of body length to include into JSON trace records, default is unlimited
+
+
+
+
+%package -n python3-apiritif
+Summary: Python framework for API testing
+Provides: python-apiritif
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-apiritif
+# Apiritif
+
+Apiritif is a number of utilities aimed to simplify the process of maintaining API tests.
+Apiritif tests fully based on python nose tests. This library can help you to develop and run your existing tests.
+In order to create any valid tests for Apiritif you can read [nose test documentation](https://nose.readthedocs.io/en/latest/testing.html).
+
+Check Apiritif version with the following command:
+```
+python -m apiritif -- version
+```
+
+Here described some features of Apiritif which can help you to create tests more easily.
+
+## Overview
+
+## HTTP Requests
+
+Apiritif allows to use simple `requests`-like API for making HTTP requests.
+
+```python
+from apiritif import http
+
+response = http.get("http://example.com")
+response.assert_ok() # will raise AssertionError if request wasn't successful
+```
+
+`http` object provides the following methods:
+```python
+from apiritif import http
+
+http.get("http://api.example.com/posts")
+http.post("http://api.example.com/posts")
+http.put("http://api.example.com/posts/1")
+http.patch("http://api.example.com/posts/1")
+http.delete("http://api.example.com/posts/1")
+http.head("http://api.example.com/posts")
+```
+
+All methods (`get`, `post`, `put`, `patch`, `delete`, `head`) support the following arguments:
+```python
+def get(address, # URL for the request
+ params=None, # URL params dict
+ headers=None, # HTTP headers
+ cookies=None, # request cookies
+ data=None, # raw request data
+ json=None, # attach JSON object as request body
+ encrypted_cert=None, # certificate to use with request
+ allow_redirects=True, # automatically follow HTTP redirects
+ timeout=30) # request timeout, by default it's 30 seconds
+```
+
+##### Certificate usage
+Currently `http` supports `pem` and `pkcs12` certificates.
+Here is an example of certificate usage:
+```python
+http.get("http://api.example.com/posts", encrypted_cert=('./cert.pem', 'passphrase'))
+```
+First parameter is path to certificate, second is the passphrase certificate encrypted with.
+
+## HTTP Targets
+
+Target is an object that captures resource name of the URL (protocol, domain, port)
+and allows to set some settings applied to all requests made for a target.
+
+
+```python
+from apiritif import http
+
+qa_env = http.target("http://192.160.0.2")
+qa_env.get("/api/v4/user")
+qa_env.get("/api/v4/user")
+```
+
+Target constructor supports the following options:
+```python
+target = apiritif.http.target(
+ address, # target base address
+ base_path=None, # base path prepended to all paths (e.g. '/api/v2')
+ use_cookies=True, # use cookies
+ additional_headers=None, # additional headers for all requests
+ keep_alive=True, # reuse opened HTTP connection
+ auto_assert_ok=True, # automatically invoke 'assert_ok' after each request
+)
+```
+
+
+## Assertions
+
+Apiritif responses provide a lot of useful assertions that can be used on responses.
+
+Here's the list of assertions that can be used:
+```python
+response = http.get("http://example.com/")
+
+# assert that request succeeded (status code is 2xx or 3xx)
+response.assert_ok()
+# assert that request has failed
+response.assert_failed()
+
+# status code based assertions
+response.assert_2xx()
+response.assert_3xx()
+response.assert_4xx()
+response.assert_5xx()
+response.assert_status_code(code)
+response.assert_not_status_code(code)
+response.assert_status_code_in(codes)
+
+# content-based assertions
+
+# assert that response body contains a string
+response.assert_in_body(member)
+
+# assert that response body doesn't contain a string
+response.assert_not_in_body(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_body(regex, match=False)
+response.assert_regex_not_in_body(regex, match=False)
+
+# assert that response has header
+response.assert_has_header(header)
+
+# assert that response has header with given value
+response.assert_header_value(header, value)
+
+# assert that response's headers contains a string
+response.assert_in_headers(member)
+response.assert_not_in_headers(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_headers(member)
+response.assert_regex_not_in_headers(member)
+
+# assert that response body matches JSONPath query
+response.assert_jsonpath(jsonpath_query, expected_value=None)
+response.assert_not_jsonpath(jsonpath_query)
+
+# assert that response body matches XPath query
+response.assert_xpath(xpath_query, parser_type='html', validate=False)
+response.assert_not_xpath(xpath_query, parser_type='html', validate=False)
+
+# assert that HTML response body contains CSS selector item
+response.assert_cssselect(selector, expected_value=None, attribute=None)
+response.assert_not_cssselect(selector, expected_value=None, attribute=None)
+
+```
+
+Note that assertions can be chained, so the following construction is entirely valid:
+```python
+
+response = http.get("http://example.com/")
+response.assert_ok().assert_in_body("Example")
+```
+
+## Transactions
+
+Apiritif allows to group multiple requests or actions into a transaction using a `transaction` context manager.
+For example when we have test action like bellow we want to execute requests according to concrete user as a separate piece.
+Also we want to process test for `users/all` page even if something wrong with previous actions.
+
+```python
+def test_with_login():
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+
+Here where we can use transaction in order to wrap login process in one block.
+
+```python
+def test_with_login():
+ with apiritif.transaction('Login'):
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+At the same time requests to `users/all` page will be executed outside of transaction even if something inside transaction fails.
+
+Transaction defines the name for the block of code. This name with execution results of this particular block will be displayed in the output report.
+
+#### Smart transactions
+
+`smart_transaction` is advanced option for test flow control (stop or continue after failed test method).
+Let see another test method example:
+
+```python
+class Tests(TestCase):
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+In this case we have multiple requests divided into blocks. I do not want to test pages under `users` space if it is not available.
+For this purpose we can use `smart_transaction`.
+
+```python
+class Tests(TestCase):
+ def setUp(self):
+ apiritif.put_into_thread_store(func_mode=True)
+
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+
+ with apiritif.smart_transaction('Availability check'):
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ with apiritif.smart_transaction('Test users pages'):
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+Now this two blocks are wrapped into `smart_transaction` which would help with error test flow handling and logging.
+
+Also each transaction defines the name for the block of code and will be displayed in the output report.
+
+Now about `apiritif.put_into_thread_store(func_mode=True)`, this is test execution mode for apiritif.
+We can execute all of the transactions in test no matter what or stop after first failed transaction.
+This flag tells to apiritif "Stop execution if some transaction failed". `False` says "Run till the end in any case".
+
+##### Nose Flow Control
+It's one more feature based on smart transactions. It changes `func_mode` if necessary to execute whole teardown block,
+intended to finalize all necessary things.
+
+```python
+def test_flow-control(self):
+ try:
+ self._method_with_exception()
+ self._skipped_method()
+ finally:
+ apiritif.set_stage("teardown")
+ self._teardown1()
+ self._teardown2()
+```
+If this test will be interrupted in `_method_with_exception`, both of teardown methods will be executed even if them raise exception.
+Please note two differences with usage of `tearDown` method of nose:
+1. all parts of teardown stage will be executed as mentioned above (will be interrupted in regular nose execution)
+2. results of teardown steps will be written by apiritif SampleWriter into output file (nose lost them as tearDown isn't recognised as test).
+
+##### Graceful shutdown
+Somethimes waiting of end of test isn't necessary and we prefer to break it but save all current results and handle all teardown steps. (see above)
+It's possible with GRACEFUL flag. To use it you can run apiritif with GRACEFUL environment variable pointed to any file name.
+Apiritif will be interrupted as soon as the file is created.
+
+## CSV Reader
+In order to use data from csv file as test parameters Apiritif provides two different csv readers.
+Simple `CSVReader` helps you to read data from file line by line and use this data wherever you need:
+
+```python
+data_reader = apiritif.CSVReader('---path to required file---')
+class Tests(TestCase):
+ def test_user_page():
+ data_reader.read_vars()
+ vars = data_reader.get_vars()
+ http.get("https://blazedemo.com/users/" + vars.user_id).assert_ok()
+```
+
+In case of multithreading testing you may need to deviate data between threads and ysu uniq lines for each thread.
+`CSVReaderPerThread` helps to solve this problem:
+
+```python
+data_per_thread_reader = apiritif.CSVReaderPerThread('---path to required file---')
+class Tests(TestCase):
+ def setUp(self):
+ data_per_thread_reader.read_vars()
+ self.vars = data_per_thread_reader.get_vars()
+
+ def test_user_page():
+ http.get("https://blazedemo.com/users/" + self.vars.user_id).assert_ok()
+```
+
+## Execution results
+
+Apiritif writes output data from tests in `apiritif.#.csv` files by default. Here `#` is number of executing process.
+The output file is similar to this:
+```csv
+timeStamp,elapsed,Latency,label,responseCode,responseMessage,success,allThreads,bytes
+1602759519185,0,0,Correct test,,,true,0,2
+1602759519186,0,0,Correct transaction,,,true,0,2
+1602759519187,0,0,Test with exception,,Exception: Horrible error,false,0,2
+```
+It contains test and transaction results for executed tests by one process.
+
+### Environment Variables
+
+There are environment variables to control length of response/request body to be written into traces and logs:
+ * `APIRITIF_TRACE_BODY_EXCLIMIT` - limit of body part to include into exception messages, default is 1024
+ * `APIRITIF_TRACE_BODY_HARDLIMIT` - limit of body length to include into JSON trace records, default is unlimited
+
+
+
+
+%package help
+Summary: Development documents and examples for apiritif
+Provides: python3-apiritif-doc
+%description help
+# Apiritif
+
+Apiritif is a number of utilities aimed to simplify the process of maintaining API tests.
+Apiritif tests fully based on python nose tests. This library can help you to develop and run your existing tests.
+In order to create any valid tests for Apiritif you can read [nose test documentation](https://nose.readthedocs.io/en/latest/testing.html).
+
+Check Apiritif version with the following command:
+```
+python -m apiritif -- version
+```
+
+Here described some features of Apiritif which can help you to create tests more easily.
+
+## Overview
+
+## HTTP Requests
+
+Apiritif allows to use simple `requests`-like API for making HTTP requests.
+
+```python
+from apiritif import http
+
+response = http.get("http://example.com")
+response.assert_ok() # will raise AssertionError if request wasn't successful
+```
+
+`http` object provides the following methods:
+```python
+from apiritif import http
+
+http.get("http://api.example.com/posts")
+http.post("http://api.example.com/posts")
+http.put("http://api.example.com/posts/1")
+http.patch("http://api.example.com/posts/1")
+http.delete("http://api.example.com/posts/1")
+http.head("http://api.example.com/posts")
+```
+
+All methods (`get`, `post`, `put`, `patch`, `delete`, `head`) support the following arguments:
+```python
+def get(address, # URL for the request
+ params=None, # URL params dict
+ headers=None, # HTTP headers
+ cookies=None, # request cookies
+ data=None, # raw request data
+ json=None, # attach JSON object as request body
+ encrypted_cert=None, # certificate to use with request
+ allow_redirects=True, # automatically follow HTTP redirects
+ timeout=30) # request timeout, by default it's 30 seconds
+```
+
+##### Certificate usage
+Currently `http` supports `pem` and `pkcs12` certificates.
+Here is an example of certificate usage:
+```python
+http.get("http://api.example.com/posts", encrypted_cert=('./cert.pem', 'passphrase'))
+```
+First parameter is path to certificate, second is the passphrase certificate encrypted with.
+
+## HTTP Targets
+
+Target is an object that captures resource name of the URL (protocol, domain, port)
+and allows to set some settings applied to all requests made for a target.
+
+
+```python
+from apiritif import http
+
+qa_env = http.target("http://192.160.0.2")
+qa_env.get("/api/v4/user")
+qa_env.get("/api/v4/user")
+```
+
+Target constructor supports the following options:
+```python
+target = apiritif.http.target(
+ address, # target base address
+ base_path=None, # base path prepended to all paths (e.g. '/api/v2')
+ use_cookies=True, # use cookies
+ additional_headers=None, # additional headers for all requests
+ keep_alive=True, # reuse opened HTTP connection
+ auto_assert_ok=True, # automatically invoke 'assert_ok' after each request
+)
+```
+
+
+## Assertions
+
+Apiritif responses provide a lot of useful assertions that can be used on responses.
+
+Here's the list of assertions that can be used:
+```python
+response = http.get("http://example.com/")
+
+# assert that request succeeded (status code is 2xx or 3xx)
+response.assert_ok()
+# assert that request has failed
+response.assert_failed()
+
+# status code based assertions
+response.assert_2xx()
+response.assert_3xx()
+response.assert_4xx()
+response.assert_5xx()
+response.assert_status_code(code)
+response.assert_not_status_code(code)
+response.assert_status_code_in(codes)
+
+# content-based assertions
+
+# assert that response body contains a string
+response.assert_in_body(member)
+
+# assert that response body doesn't contain a string
+response.assert_not_in_body(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_body(regex, match=False)
+response.assert_regex_not_in_body(regex, match=False)
+
+# assert that response has header
+response.assert_has_header(header)
+
+# assert that response has header with given value
+response.assert_header_value(header, value)
+
+# assert that response's headers contains a string
+response.assert_in_headers(member)
+response.assert_not_in_headers(member)
+
+# search (or match) response body with a regex
+response.assert_regex_in_headers(member)
+response.assert_regex_not_in_headers(member)
+
+# assert that response body matches JSONPath query
+response.assert_jsonpath(jsonpath_query, expected_value=None)
+response.assert_not_jsonpath(jsonpath_query)
+
+# assert that response body matches XPath query
+response.assert_xpath(xpath_query, parser_type='html', validate=False)
+response.assert_not_xpath(xpath_query, parser_type='html', validate=False)
+
+# assert that HTML response body contains CSS selector item
+response.assert_cssselect(selector, expected_value=None, attribute=None)
+response.assert_not_cssselect(selector, expected_value=None, attribute=None)
+
+```
+
+Note that assertions can be chained, so the following construction is entirely valid:
+```python
+
+response = http.get("http://example.com/")
+response.assert_ok().assert_in_body("Example")
+```
+
+## Transactions
+
+Apiritif allows to group multiple requests or actions into a transaction using a `transaction` context manager.
+For example when we have test action like bellow we want to execute requests according to concrete user as a separate piece.
+Also we want to process test for `users/all` page even if something wrong with previous actions.
+
+```python
+def test_with_login():
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+
+Here where we can use transaction in order to wrap login process in one block.
+
+```python
+def test_with_login():
+ with apiritif.transaction('Login'):
+ user_credentials = data_mock.get_my_user()
+ http.get("https://blazedemo.com/user/login?id="+user_credentials.id).assert_ok()
+ http.get("https://blazedemo.com/user/id/personalPage").assert_ok()
+ http.get("https://blazedemo.com/user/id/getPersonalData").assert_ok()
+
+ http.get("https://blazedemo.com/users/all").assert_ok()
+```
+At the same time requests to `users/all` page will be executed outside of transaction even if something inside transaction fails.
+
+Transaction defines the name for the block of code. This name with execution results of this particular block will be displayed in the output report.
+
+#### Smart transactions
+
+`smart_transaction` is advanced option for test flow control (stop or continue after failed test method).
+Let see another test method example:
+
+```python
+class Tests(TestCase):
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+In this case we have multiple requests divided into blocks. I do not want to test pages under `users` space if it is not available.
+For this purpose we can use `smart_transaction`.
+
+```python
+class Tests(TestCase):
+ def setUp(self):
+ apiritif.put_into_thread_store(func_mode=True)
+
+ def test_available_pages():
+ http.get("https://blazedemo.com/").assert_ok()
+
+ with apiritif.smart_transaction('Availability check'):
+ http.get("https://blazedemo.com/users").assert_ok()
+
+ with apiritif.smart_transaction('Test users pages'):
+ http.get("https://blazedemo.com/users/search").assert_ok()
+ http.get("https://blazedemo.com/users/count").assert_ok()
+ http.get("https://blazedemo.com/users/login").assert_ok()
+
+ http.get("https://blazedemo.com/contactUs").assert_ok()
+ http.get("https://blazedemo.com/copyright").assert_ok()
+```
+Now this two blocks are wrapped into `smart_transaction` which would help with error test flow handling and logging.
+
+Also each transaction defines the name for the block of code and will be displayed in the output report.
+
+Now about `apiritif.put_into_thread_store(func_mode=True)`, this is test execution mode for apiritif.
+We can execute all of the transactions in test no matter what or stop after first failed transaction.
+This flag tells to apiritif "Stop execution if some transaction failed". `False` says "Run till the end in any case".
+
+##### Nose Flow Control
+It's one more feature based on smart transactions. It changes `func_mode` if necessary to execute whole teardown block,
+intended to finalize all necessary things.
+
+```python
+def test_flow-control(self):
+ try:
+ self._method_with_exception()
+ self._skipped_method()
+ finally:
+ apiritif.set_stage("teardown")
+ self._teardown1()
+ self._teardown2()
+```
+If this test will be interrupted in `_method_with_exception`, both of teardown methods will be executed even if them raise exception.
+Please note two differences with usage of `tearDown` method of nose:
+1. all parts of teardown stage will be executed as mentioned above (will be interrupted in regular nose execution)
+2. results of teardown steps will be written by apiritif SampleWriter into output file (nose lost them as tearDown isn't recognised as test).
+
+##### Graceful shutdown
+Somethimes waiting of end of test isn't necessary and we prefer to break it but save all current results and handle all teardown steps. (see above)
+It's possible with GRACEFUL flag. To use it you can run apiritif with GRACEFUL environment variable pointed to any file name.
+Apiritif will be interrupted as soon as the file is created.
+
+## CSV Reader
+In order to use data from csv file as test parameters Apiritif provides two different csv readers.
+Simple `CSVReader` helps you to read data from file line by line and use this data wherever you need:
+
+```python
+data_reader = apiritif.CSVReader('---path to required file---')
+class Tests(TestCase):
+ def test_user_page():
+ data_reader.read_vars()
+ vars = data_reader.get_vars()
+ http.get("https://blazedemo.com/users/" + vars.user_id).assert_ok()
+```
+
+In case of multithreading testing you may need to deviate data between threads and ysu uniq lines for each thread.
+`CSVReaderPerThread` helps to solve this problem:
+
+```python
+data_per_thread_reader = apiritif.CSVReaderPerThread('---path to required file---')
+class Tests(TestCase):
+ def setUp(self):
+ data_per_thread_reader.read_vars()
+ self.vars = data_per_thread_reader.get_vars()
+
+ def test_user_page():
+ http.get("https://blazedemo.com/users/" + self.vars.user_id).assert_ok()
+```
+
+## Execution results
+
+Apiritif writes output data from tests in `apiritif.#.csv` files by default. Here `#` is number of executing process.
+The output file is similar to this:
+```csv
+timeStamp,elapsed,Latency,label,responseCode,responseMessage,success,allThreads,bytes
+1602759519185,0,0,Correct test,,,true,0,2
+1602759519186,0,0,Correct transaction,,,true,0,2
+1602759519187,0,0,Test with exception,,Exception: Horrible error,false,0,2
+```
+It contains test and transaction results for executed tests by one process.
+
+### Environment Variables
+
+There are environment variables to control length of response/request body to be written into traces and logs:
+ * `APIRITIF_TRACE_BODY_EXCLIMIT` - limit of body part to include into exception messages, default is 1024
+ * `APIRITIF_TRACE_BODY_HARDLIMIT` - limit of body length to include into JSON trace records, default is unlimited
+
+
+
+
+%prep
+%autosetup -n apiritif-1.1.3
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-apiritif -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Tue Apr 11 2023 Python_Bot <Python_Bot@openeuler.org> - 1.1.3-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..3805bb0
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+81ed36b292f254c815302d841c666195 apiritif-1.1.3.tar.gz