# Unittest soft asserts.
![PyPI](https://img.shields.io/pypi/v/nrt-unittest-soft-asserts?color=blueviolet&style=plastic)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/nrt-unittest-soft-asserts?color=greens&style=plastic)
![PyPI - License](https://img.shields.io/pypi/l/nrt-unittest-soft-asserts?color=blue&style=plastic)
![PyPI - Downloads](https://img.shields.io/pypi/dd/nrt-unittest-soft-asserts?style=plastic)
![PyPI - Downloads](https://img.shields.io/pypi/dm/nrt-unittest-soft-asserts?color=yellow&style=plastic)
[![Coverage Status](https://coveralls.io/repos/github/etuzon/python-nrt-unittest-soft-asserts/badge.svg)](https://coveralls.io/github/etuzon/pytohn-nrt-unittest-soft-asserts)
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/etuzon/python-nrt-unittest-soft-asserts?style=plastic)
![GitHub last commit](https://img.shields.io/github/last-commit/etuzon/python-nrt-unittest-soft-asserts?style=plastic)
[![DeepSource](https://app.deepsource.com/gh/etuzon/python-nrt-unittest-soft-asserts.svg/?label=active+issues&token=WQz2lXCAZSwv8ndUhX7E7IQH)](https://app.deepsource.com/gh/etuzon/python-nrt-unittest-soft-asserts/?ref=repository-badge)
### Supported asserts:
| Assert | Description | Example | Return |
|------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| soft_assert_true(condition, message=None) | Verify that condition is True. | self.soft_assert_true(a == b) | True if assertion passes, False if assertion fails. |
| soft_assert_false(condition, message=None) | Verify that condition is False. | self.soft_assert_false(a == b) | True if assertion passes, False if assertion fails. |
| soft_assert_equal(first, second, message=None) | Verify that first is equal to second. | self.soft_assert_equal(a, b) | True if assertion passes, False if assertion fails. |
| soft_assert_not_equal(first, second, message=None) | Verify that first is not equal to second. | self.soft_assert_not_equal(a, b) | True if assertion passes, False if assertion fails. |
| soft_assert_is(first, second, message=None) | Verify that first and second are the same object. | self.soft_assert_is(a, b) | True if assertion passes, False if assertion fails. |
| soft_assert_is_not(first, second, message=None) | Verify that first and second are not the same object. | self.soft_assert_is_not(a, b) | True if assertion passes, False if assertion fails. |
| soft_assert_is_none(obj, message=None) | Verify that obj is None. | self.soft_assert_is_none(a) | True if assertion passes, False if assertion fails. |
| soft_assert_is_not_none(obj, message=None) | Verify that obj is not None. | self.soft_assert_is_not_none(a) | True if assertion passes, False if assertion fails. |
| soft_assert_in(obj, container, message=None) | Verify that obj is in container. | self.soft_assert_in(a, [a, b, c]) | True if assertion passes, False if assertion fails. |
| soft_assert_not_in(obj, container, message=None) | Verify that obj is not in container. | self.soft_assert_not_in(a, [b, c]) | True if assertion passes, False if assertion fails. |
| soft_assert_is_instance(obj, cls, message=None) | Verify that obj is instance of cls. | self.soft_assert_is_instance(a, A) | True if assertion passes, False if assertion fails. |
| soft_assert_is_not_instance(obj, cls, message=None) | Verify that obj is not instance of cls. | self.soft_assert_is_not_instance(a, B) | True if assertion passes, False if assertion fails. |
| soft_assert_almost_equal(first, second, delta, message=None) | Verify that first is almost equal to second.<br/>and the different is equal or less to delta. | self.soft_assert_almost_equal(1.001, 1.002, 0.1) | True if assertion passes, False if assertion fails. |
| soft_assert_not_almost_equal(first, second, delta, message=None) | Verify that first is not almost equal to second<br/>and the different is more than delta. | self.soft_assert_not_almost_equal(1.001, 1.002, 0.0001) | True if assertion passes, False if assertion fails. |
| soft_assert_raises(exception, method: Callable, *args, **kwargs) | Verify that method execution raise exception. | self.soft_assert_raises(TypeError, sum, 'a', 2) | True if assertion passes, False if assertion fails. |
| soft_assert_raises_with(exception, message=None) | Verify that execution in 'with' block raise exception. | with self.soft_assert_raised_with(ValueError):<br/> raise ValueError(ERROR_MESSAGE_1) | |
In the end of each test, the soft asserts will be verified and the test will be marked as failed if any of the asserts failed.<br/>
To verify the soft asserts in the middle of the test, call `self.soft_assert_all()`.<br/>
<br/>
soft_assert_all() will raise _AssertionError_ if any of the asserts failed.
<br/>
### Steps
Each testing section can be divided to steps. The meaning of this is that if one of the asserts in a step failed,<br/>
then the step will be entered to list of failure steps and next test can be skipped if it is depended on the failed step.<br/>
#### Example:
To make test be skipped if step failed, a custom decorator should be created.
This is an example of such custom decorator, but user can create its own custom decorator.
```python
import functools
from nrt_unittest_soft_asserts.soft_asserts import SoftAsserts
# Custom decorator to skip test if one of the steps failed.
def skip_steps(skip_steps_list: list[str]):
def decorator(test_method):
@functools.wraps(test_method)
def wrapper(self, *args, **kwargs):
for step in skip_steps_list:
if self.is_step_in_failure_steps(step):
self.skipTest(f'Skipped because step [{step}] failed.')
return test_method(self, *args, **kwargs)
return wrapper
return decorator
class SoftAssertsExamplesTests(SoftAsserts):
STEP_1 = 'step 1'
STEP_2 = 'step 2'
STEP_3 = 'step 3'
def test_01_assert_with_steps_test_will_fail(self):
self.set_step(self.STEP_1)
# result is False
result = self.soft_assert_true(False)
self.set_step(self.STEP_2)
self.soft_assert_true(False)
# From this code section steps will not be attached to failure asserts
self.unset_step()
self.soft_assert_true(False)
self.soft_assert_all()
@skip_steps([STEP_1])
def test_02_skip_if_step_1_fail(self):
self.soft_assert_true(False)
self.soft_assert_all()
@skip_steps([STEP_2])
def test_03_skip_if_step_2_fail(self):
self.soft_assert_true(False)
self.soft_assert_all()
@skip_steps([STEP_1, STEP_2])
def test_04_skip_if_step_1_or_step2_fail(self):
self.soft_assert_true(False)
self.soft_assert_all()
@skip_steps([STEP_3])
def test_05_skip_if_step_3_fail_will_not_be_skipped(self):
"""
Test should not be skipped because {STEP_3} is not in failure steps.
"""
# result is True
result = self.soft_assert_true(True)
self.soft_assert_all()
```
### Print error on each failed assert
Each assert failure can be printed.<br/>
This can be done by adding logger or by adding a print method.
- In case a logger will be added, then logger.error(message) will be used.
- In case a print method will be added, then print_method(message) will be used.
- logger and print method cannot be added together.
#### Error format
`message [file_path: line_number] code_line`
#### logger example:
```python
import logging
from nrt_unittest_soft_asserts.soft_asserts import SoftAsserts
class SoftAssertsWithLoggerTests(SoftAsserts):
logger = logging.getLogger('test')
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.set_logger(cls.logger)
def test_assert_true_fail(self):
i = 1
j = 2
# logger.error() will print messages to console for each assert that fails
self.soft_assert_true(i + j == 5)
self.soft_assert_equal(i, j, f'{i} is different from {j}')
self.soft_assert_all()
```
#### print method example:
```python
from nrt_unittest_soft_asserts.soft_asserts import SoftAsserts
class SoftAssertsWithPrintMethodTests(SoftAsserts):
def setUp(self):
super().setUp()
self.set_print_method(self.__print_message)
def test_assert_true_fail(self):
i = 1
j = 2
# self.__print_message() will print messages
# to console for each assert that fails
self.soft_assert_true(i + j == 5)
self.soft_assert_equal(i, j, f'{i} is different from {j}')
self.soft_assert_all()
def __print_message(self, msg):
print()
```
Wiki: https://github.com/etuzon/python-nrt-unittest-soft-asserts/wiki
Raw data
{
"_id": null,
"home_page": "https://github.com/etuzon/python-nrt-unittest-soft-asserts",
"name": "nrt-unittest-soft-asserts",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "python, python3, python-3, nrt, unittest, soft, assert, asserts, assertion, assertions, soft-assert, soft-asserts, soft-assertion, soft-assertions, nrt-unittest-soft-asserts",
"author": "Eyal Tuzon",
"author_email": "Eyal Tuzon <eyal.tuzon.dev@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/71/98/93ad6e073a9975de4ea96d87a5680d6f63af39b6fec7a01060346e23d650/nrt_unittest_soft_asserts-1.1.0.tar.gz",
"platform": null,
"description": "# Unittest soft asserts.\r\n\r\n![PyPI](https://img.shields.io/pypi/v/nrt-unittest-soft-asserts?color=blueviolet&style=plastic)\r\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/nrt-unittest-soft-asserts?color=greens&style=plastic)\r\n![PyPI - License](https://img.shields.io/pypi/l/nrt-unittest-soft-asserts?color=blue&style=plastic)\r\n![PyPI - Downloads](https://img.shields.io/pypi/dd/nrt-unittest-soft-asserts?style=plastic)\r\n![PyPI - Downloads](https://img.shields.io/pypi/dm/nrt-unittest-soft-asserts?color=yellow&style=plastic)\r\n[![Coverage Status](https://coveralls.io/repos/github/etuzon/python-nrt-unittest-soft-asserts/badge.svg)](https://coveralls.io/github/etuzon/pytohn-nrt-unittest-soft-asserts)\r\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/etuzon/python-nrt-unittest-soft-asserts?style=plastic)\r\n![GitHub last commit](https://img.shields.io/github/last-commit/etuzon/python-nrt-unittest-soft-asserts?style=plastic)\r\n[![DeepSource](https://app.deepsource.com/gh/etuzon/python-nrt-unittest-soft-asserts.svg/?label=active+issues&token=WQz2lXCAZSwv8ndUhX7E7IQH)](https://app.deepsource.com/gh/etuzon/python-nrt-unittest-soft-asserts/?ref=repository-badge)\r\n\r\n### Supported asserts:\r\n\r\n| Assert | Description | Example | Return |\r\n|------------------------------------------------------------------|-----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|\r\n| soft_assert_true(condition, message=None) | Verify that condition is True. | self.soft_assert_true(a == b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_false(condition, message=None) | Verify that condition is False. | self.soft_assert_false(a == b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_equal(first, second, message=None) | Verify that first is equal to second. | self.soft_assert_equal(a, b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_not_equal(first, second, message=None) | Verify that first is not equal to second. | self.soft_assert_not_equal(a, b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is(first, second, message=None) | Verify that first and second are the same object. | self.soft_assert_is(a, b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is_not(first, second, message=None) | Verify that first and second are not the same object. | self.soft_assert_is_not(a, b) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is_none(obj, message=None) | Verify that obj is None. | self.soft_assert_is_none(a) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is_not_none(obj, message=None) | Verify that obj is not None. | self.soft_assert_is_not_none(a) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_in(obj, container, message=None) | Verify that obj is in container. | self.soft_assert_in(a, [a, b, c]) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_not_in(obj, container, message=None) | Verify that obj is not in container. | self.soft_assert_not_in(a, [b, c]) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is_instance(obj, cls, message=None) | Verify that obj is instance of cls. | self.soft_assert_is_instance(a, A) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_is_not_instance(obj, cls, message=None) | Verify that obj is not instance of cls. | self.soft_assert_is_not_instance(a, B) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_almost_equal(first, second, delta, message=None) | Verify that first is almost equal to second.<br/>and the different is equal or less to delta. | self.soft_assert_almost_equal(1.001, 1.002, 0.1) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_not_almost_equal(first, second, delta, message=None) | Verify that first is not almost equal to second<br/>and the different is more than delta. | self.soft_assert_not_almost_equal(1.001, 1.002, 0.0001) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_raises(exception, method: Callable, *args, **kwargs) | Verify that method execution raise exception. | self.soft_assert_raises(TypeError, sum, 'a', 2) | True if assertion passes, False if assertion fails. |\r\n| soft_assert_raises_with(exception, message=None) | Verify that execution in 'with' block raise exception. | with self.soft_assert_raised_with(ValueError):<br/> raise ValueError(ERROR_MESSAGE_1) | |\r\n \r\n\r\nIn the end of each test, the soft asserts will be verified and the test will be marked as failed if any of the asserts failed.<br/>\r\nTo verify the soft asserts in the middle of the test, call `self.soft_assert_all()`.<br/>\r\n<br/>\r\nsoft_assert_all() will raise _AssertionError_ if any of the asserts failed.\r\n<br/>\r\n\r\n### Steps\r\n\r\nEach testing section can be divided to steps. The meaning of this is that if one of the asserts in a step failed,<br/>\r\nthen the step will be entered to list of failure steps and next test can be skipped if it is depended on the failed step.<br/> \r\n\r\n#### Example:\r\n\r\nTo make test be skipped if step failed, a custom decorator should be created.\r\n\r\nThis is an example of such custom decorator, but user can create its own custom decorator.\r\n\r\n\r\n```python\r\nimport functools\r\nfrom nrt_unittest_soft_asserts.soft_asserts import SoftAsserts\r\n\r\n# Custom decorator to skip test if one of the steps failed.\r\ndef skip_steps(skip_steps_list: list[str]):\r\n def decorator(test_method):\r\n @functools.wraps(test_method)\r\n def wrapper(self, *args, **kwargs):\r\n for step in skip_steps_list:\r\n if self.is_step_in_failure_steps(step):\r\n self.skipTest(f'Skipped because step [{step}] failed.')\r\n return test_method(self, *args, **kwargs)\r\n\r\n return wrapper\r\n\r\n return decorator\r\n\r\n\r\nclass SoftAssertsExamplesTests(SoftAsserts):\r\n STEP_1 = 'step 1'\r\n STEP_2 = 'step 2'\r\n STEP_3 = 'step 3'\r\n \r\n def test_01_assert_with_steps_test_will_fail(self):\r\n self.set_step(self.STEP_1)\r\n # result is False\r\n result = self.soft_assert_true(False)\r\n\r\n self.set_step(self.STEP_2)\r\n self.soft_assert_true(False)\r\n\r\n # From this code section steps will not be attached to failure asserts\r\n self.unset_step()\r\n self.soft_assert_true(False)\r\n\r\n self.soft_assert_all()\r\n\r\n @skip_steps([STEP_1])\r\n def test_02_skip_if_step_1_fail(self):\r\n self.soft_assert_true(False)\r\n self.soft_assert_all()\r\n\r\n @skip_steps([STEP_2])\r\n def test_03_skip_if_step_2_fail(self):\r\n self.soft_assert_true(False)\r\n self.soft_assert_all()\r\n\r\n @skip_steps([STEP_1, STEP_2])\r\n def test_04_skip_if_step_1_or_step2_fail(self):\r\n self.soft_assert_true(False)\r\n self.soft_assert_all()\r\n\r\n @skip_steps([STEP_3])\r\n def test_05_skip_if_step_3_fail_will_not_be_skipped(self):\r\n \"\"\"\r\n Test should not be skipped because {STEP_3} is not in failure steps.\r\n \"\"\"\r\n # result is True\r\n result = self.soft_assert_true(True)\r\n self.soft_assert_all()\r\n```\r\n\r\n### Print error on each failed assert\r\n\r\nEach assert failure can be printed.<br/>\r\nThis can be done by adding logger or by adding a print method.\r\n - In case a logger will be added, then logger.error(message) will be used.\r\n - In case a print method will be added, then print_method(message) will be used.\r\n - logger and print method cannot be added together.\r\n\r\n#### Error format\r\n\r\n`message [file_path: line_number] code_line`\r\n\r\n#### logger example:\r\n\r\n```python\r\nimport logging\r\nfrom nrt_unittest_soft_asserts.soft_asserts import SoftAsserts\r\n\r\n\r\nclass SoftAssertsWithLoggerTests(SoftAsserts):\r\n logger = logging.getLogger('test')\r\n\r\n @classmethod\r\n def setUpClass(cls):\r\n super().setUpClass()\r\n cls.set_logger(cls.logger)\r\n \r\n def test_assert_true_fail(self):\r\n i = 1\r\n j = 2\r\n # logger.error() will print messages to console for each assert that fails\r\n self.soft_assert_true(i + j == 5)\r\n self.soft_assert_equal(i, j, f'{i} is different from {j}')\r\n self.soft_assert_all()\r\n```\r\n\r\n#### print method example:\r\n\r\n```python\r\nfrom nrt_unittest_soft_asserts.soft_asserts import SoftAsserts\r\n\r\nclass SoftAssertsWithPrintMethodTests(SoftAsserts):\r\n \r\n def setUp(self):\r\n super().setUp()\r\n self.set_print_method(self.__print_message)\r\n\r\n def test_assert_true_fail(self):\r\n i = 1\r\n j = 2\r\n # self.__print_message() will print messages \r\n # to console for each assert that fails\r\n self.soft_assert_true(i + j == 5)\r\n self.soft_assert_equal(i, j, f'{i} is different from {j}')\r\n self.soft_assert_all()\r\n \r\n def __print_message(self, msg):\r\n print()\r\n```\r\n\r\nWiki: https://github.com/etuzon/python-nrt-unittest-soft-asserts/wiki\r\n",
"bugtrack_url": null,
"license": null,
"summary": "Soft asserts for unittest",
"version": "1.1.0",
"project_urls": {
"Bug Tracker": "https://github.com/etuzon/python-nrt-unittest-soft-asserts/issues",
"Homepage": "https://github.com/etuzon/python-nrt-unittest-soft-asserts",
"documentation": "https://github.com/etuzon/python-nrt-unittest-soft-asserts/wiki"
},
"split_keywords": [
"python",
" python3",
" python-3",
" nrt",
" unittest",
" soft",
" assert",
" asserts",
" assertion",
" assertions",
" soft-assert",
" soft-asserts",
" soft-assertion",
" soft-assertions",
" nrt-unittest-soft-asserts"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "0a213219ec704b13dc025060d09b24b7ecc30eed57520a88b98740154186fec1",
"md5": "d45d2405892f8e90e1adc7b2977b1455",
"sha256": "8a84ef4292488aa54b05e11a45e44c71157e00212af343aacfb67be941b0a66b"
},
"downloads": -1,
"filename": "nrt_unittest_soft_asserts-1.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d45d2405892f8e90e1adc7b2977b1455",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 7020,
"upload_time": "2024-07-05T13:23:18",
"upload_time_iso_8601": "2024-07-05T13:23:18.142971Z",
"url": "https://files.pythonhosted.org/packages/0a/21/3219ec704b13dc025060d09b24b7ecc30eed57520a88b98740154186fec1/nrt_unittest_soft_asserts-1.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "719893ad6e073a9975de4ea96d87a5680d6f63af39b6fec7a01060346e23d650",
"md5": "1f88dd6d6860083ac18b55b3b87dcd55",
"sha256": "cf209b160040e2ed2e453f71411ecbf46cc69f82d3672d702d3a2999afb8eeac"
},
"downloads": -1,
"filename": "nrt_unittest_soft_asserts-1.1.0.tar.gz",
"has_sig": false,
"md5_digest": "1f88dd6d6860083ac18b55b3b87dcd55",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 7589,
"upload_time": "2024-07-05T13:23:20",
"upload_time_iso_8601": "2024-07-05T13:23:20.750340Z",
"url": "https://files.pythonhosted.org/packages/71/98/93ad6e073a9975de4ea96d87a5680d6f63af39b6fec7a01060346e23d650/nrt_unittest_soft_asserts-1.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-05 13:23:20",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "etuzon",
"github_project": "python-nrt-unittest-soft-asserts",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [],
"lcname": "nrt-unittest-soft-asserts"
}