core-tests 2.0.4__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-tests
3
- Version: 2.0.4
3
+ Version: 2.1.0
4
4
  Summary: It contains common elements for testing purposes...
5
5
  Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
6
6
  Maintainer: Alejandro Cora González
@@ -22,26 +22,33 @@ Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
25
27
  Requires-Python: >=3.9
26
28
  Description-Content-Type: text/x-rst
27
29
  License-File: LICENSE
28
30
  Requires-Dist: click>=8.1.8
29
31
  Requires-Dist: coverage>=7.7.1
30
32
  Requires-Dist: environs>=14.1.1
31
- Requires-Dist: pytest>=7.4.0
32
- Requires-Dist: pytest-xdist>=3.5.0
33
33
  Provides-Extra: dev
34
- Requires-Dist: core-dev-tools>=1.0.1; extra == "dev"
34
+ Requires-Dist: core-dev-tools>=2.0.0; extra == "dev"
35
35
  Dynamic: license-file
36
36
 
37
37
  core-tests
38
38
  ===============================================================================
39
39
 
40
- This project contains basic elements for testing purposes and the ability
41
- to run (via console commands) tests and code coverage (unittest-based). This way, we can
42
- stick to the `DRY -- Don't Repeat Yourself` principle and avoid code duplication
43
- in each python project where tests coverage and tests execution are
44
- expected...
40
+ A reusable library that provides CLI commands for running ``unittest``-based
41
+ tests and generating code coverage reports. It wraps Python's built-in
42
+ ``unittest`` framework and ``coverage`` into a ``Click`` command group so
43
+ consuming projects can use ``python manager.py run-tests`` and
44
+ ``python manager.py run-coverage`` without duplicating that logic across
45
+ every project in the ecosystem.
46
+
47
+ This library is intentionally scoped to ``unittest`` and ``coverage``.
48
+ If your project requires ``pytest``-specific features (fixtures, parametrize,
49
+ plugins, parallel execution), install ``pytest`` directly or via
50
+ ``core-dev-tools`` and invoke it standalone — it is a better fit for that use
51
+ case than routing it through this abstraction layer.
45
52
 
46
53
  ===============================================================================
47
54
 
@@ -76,32 +83,35 @@ Install from PyPI using pip:
76
83
  .. code-block:: bash
77
84
 
78
85
  pip install core-tests
79
-
80
- Or using uv:
81
-
82
- .. code-block:: bash
83
-
84
- uv pip install core-tests
86
+ uv pip install core-tests # Or using UV...
85
87
 
86
88
 
87
89
  Features
88
90
  ===============================================================================
89
91
 
90
- * **Dual Test Engine Support**: Run tests using either `unittest` or `pytest` frameworks
91
- * **Flexible Test Discovery**: Supports multiple file patterns:
92
- - `test_*.py` (standard pattern)
93
- - `*_test.py` (alternative pattern)
94
- - `tests_*.py` (custom pattern)
95
- * **Custom Pattern Support**: Specify custom file patterns using the `--pattern` flag
96
- * **Test Organization**: Run tests by type (unit, integration, functional, etc.)
97
- * **Coverage Reports**: Generate coverage reports with both frameworks
98
- * **CLI Integration**: Easy integration via Click command collections
92
+ * **Unified CLI abstraction**: Expose ``run-tests`` and ``run-coverage`` in any
93
+ project without duplicating boilerplate — just wire ``cli_tests`` into your
94
+ ``CommandCollection``.
95
+ * **Flexible Test Discovery**: Supports multiple file patterns out of the box:
96
+
97
+ - ``test_*.py`` (standard pattern)
98
+ - ``*_test.py`` (alternative pattern)
99
+ - ``tests_*.py`` (custom pattern)
100
+
101
+ * **Custom Pattern Support**: Override discovery with ``--pattern`` for
102
+ non-standard file layouts.
103
+ * **Test Organization**: Target specific test directories (unit, integration,
104
+ functional, etc.) via ``--test-type``.
105
+ * **Branch Coverage Reports**: Generate branch-level coverage reports and
106
+ optional HTML output.
107
+ * **DRY principle**: One implementation shared across all projects in the
108
+ ecosystem.
99
109
 
100
110
 
101
111
  How to Use
102
112
  ===============================================================================
103
113
 
104
- Create a ``manager.py`` file in your project root to integrate
114
+ Create a ``manager.py`` file in your project root to integrate
105
115
  the test commands:
106
116
 
107
117
  .. code-block:: python
@@ -116,7 +126,7 @@ the test commands:
116
126
 
117
127
  This setup provides two commands:
118
128
 
119
- * ``run-tests``: Execute test suites with unittest or pytest
129
+ * ``run-tests``: Execute unittest-based test suites
120
130
  * ``run-coverage``: Generate code coverage reports
121
131
 
122
132
  Example usage:
@@ -124,7 +134,7 @@ Example usage:
124
134
  .. code-block:: bash
125
135
 
126
136
  python manager.py run-tests --test-type unit
127
- python manager.py run-coverage --engine pytest
137
+ python manager.py run-coverage
128
138
 
129
139
 
130
140
  Available Commands
@@ -133,49 +143,48 @@ Available Commands
133
143
  run-tests
134
144
  -------------------------------------------------------------------------------
135
145
 
136
- Execute test suites with flexible options:
146
+ Execute unittest-based test suites with flexible options:
137
147
 
138
148
  **Options:**
139
149
 
140
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
141
- * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``, ``integration``, ``functional``)
142
- * ``--pattern``: File pattern to match test files (e.g., ``*.py``, ``test_*.py``). Works with both engines.
150
+ * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``,
151
+ ``integration``, ``functional``). Default: ``unit``
152
+ * ``--pattern``: File pattern to match test files (e.g., ``*.py``,
153
+ ``test_*.py``). Defaults to multi-pattern discovery.
143
154
 
144
155
  **Examples:**
145
156
 
146
157
  .. code-block:: bash
147
158
 
148
- # Run unit tests with unittest (default)
159
+ # Run unit tests (default)
149
160
  python manager.py run-tests --test-type unit
150
161
 
151
- # Run integration tests with pytest
152
- python manager.py run-tests --engine pytest --test-type integration
162
+ # Run integration tests
163
+ python manager.py run-tests --test-type integration
153
164
 
154
- # Run tests with custom pattern
155
- python manager.py run-tests --test-type functional --pattern "test_*.py"
165
+ # Run tests with a custom file pattern
166
+ python manager.py run-tests --test-type functional --pattern "*.py"
156
167
 
157
- # Run all tests in a custom folder
168
+ # Run tests in a custom folder
158
169
  python manager.py run-tests --test-type "custom_folder"
159
170
 
160
171
 
161
172
  run-coverage
162
173
  -------------------------------------------------------------------------------
163
174
 
164
- Generate code coverage reports:
175
+ Generate code coverage reports across all test directories:
165
176
 
166
177
  **Options:**
167
178
 
168
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
179
+ * ``--save-report``: Save HTML and data coverage reports to disk.
180
+ Default: ``True``
169
181
 
170
182
  **Examples:**
171
183
 
172
184
  .. code-block:: bash
173
185
 
174
- # Generate coverage with unittest
175
186
  python manager.py run-coverage
176
-
177
- # Generate coverage with pytest
178
- python manager.py run-coverage --engine pytest
187
+ python manager.py run-coverage --save-report false
179
188
 
180
189
 
181
190
  Quick Start
@@ -217,78 +226,32 @@ Tests and Coverage
217
226
 
218
227
  python manager.py run-tests --test-type unit
219
228
  python manager.py run-tests --test-type integration
220
- python manager.py run-tests --test-type "another folder that contains test cases under ./tests"
221
229
  python manager.py run-tests --test-type functional --pattern "*.py"
230
+ python manager.py run-coverage
222
231
 
223
232
 
224
- Using PyTest
233
+ Using pytest directly
225
234
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
226
235
 
227
- The `unittest` framework cannot discover or run pytest-style tests, it is designed to
228
- discover and run tests that are subclasses of `unittest.TestCase` and follow its
229
- conventions. Pytest-style tests (i.e., functions named test_* that are not inside a
230
- `unittest.TestCase` class, or tests using pytest fixtures, parametrize, etc.) are not
231
- recognized by unittest's discovery mechanism, `unittest` will simply ignore standalone
232
- test functions and any pytest-specific features...
233
-
234
- That's why you can use PyTest if required.
236
+ ``unittest`` cannot discover standalone ``test_*`` functions or use pytest
237
+ fixtures. If your project relies on those features, invoke ``pytest`` directly:
235
238
 
236
239
  .. code-block:: bash
237
240
 
238
- python manager.py run-tests --engine pytest
241
+ pytest tests/unit/
242
+ pytest -n auto --cov=your_package --cov-report=html
239
243
 
240
- ..
241
-
242
- Test coverage
243
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
244
+ Install ``pytest`` via ``pip`` or through ``core-dev-tools``:
244
245
 
245
246
  .. code-block:: bash
246
247
 
247
- python manager.py run-coverage # For `unittest` framework...
248
- python manager.py run-coverage --engine pytest # For `PyTest`...
249
- pytest -n auto --cov=core_tests --cov-report=html # Direct `pytest` execution...
248
+ pip install pytest pytest-xdist pytest-cov
249
+ # or
250
+ pip install ".[dev]" # if core-dev-tools includes pytest
250
251
 
251
252
  ..
252
253
 
253
254
 
254
- Best Practices
255
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
256
-
257
- When working with pytest, consider these optimization strategies:
258
-
259
- 1. **Use parallel execution for independent tests:**
260
-
261
- .. code-block:: bash
262
-
263
- pytest -n auto
264
-
265
- ..
266
-
267
- 2. **Run fast unit tests first during development:**
268
-
269
- .. code-block:: bash
270
-
271
- pytest tests/unit/ -n auto
272
-
273
- ..
274
-
275
- 3. **Run functional tests with limited parallelism:**
276
-
277
- .. code-block:: bash
278
-
279
- pytest tests/functional/ -n 2 # Avoid AWS rate limits
280
-
281
- ..
282
-
283
- 4. **Use markers to run specific test subsets:**
284
-
285
- .. code-block:: bash
286
-
287
- pytest -m "unit and not slow" -n auto
288
-
289
- ..
290
-
291
-
292
255
  Contributing
293
256
  ===============================================================================
294
257
 
@@ -297,7 +260,7 @@ Contributions are welcome! Please:
297
260
  1. Fork the repository
298
261
  2. Create a feature branch
299
262
  3. Write tests for new functionality
300
- 4. Ensure all tests pass: ``pytest -n auto``
263
+ 4. Ensure all tests pass: ``python manager.py run-tests --test-type unit``
301
264
  5. Run linting: ``pylint core_tests``
302
265
  6. Run security checks: ``bandit -r core_tests``
303
266
  7. Submit a pull request
@@ -1,11 +1,18 @@
1
1
  core-tests
2
2
  ===============================================================================
3
3
 
4
- This project contains basic elements for testing purposes and the ability
5
- to run (via console commands) tests and code coverage (unittest-based). This way, we can
6
- stick to the `DRY -- Don't Repeat Yourself` principle and avoid code duplication
7
- in each python project where tests coverage and tests execution are
8
- expected...
4
+ A reusable library that provides CLI commands for running ``unittest``-based
5
+ tests and generating code coverage reports. It wraps Python's built-in
6
+ ``unittest`` framework and ``coverage`` into a ``Click`` command group so
7
+ consuming projects can use ``python manager.py run-tests`` and
8
+ ``python manager.py run-coverage`` without duplicating that logic across
9
+ every project in the ecosystem.
10
+
11
+ This library is intentionally scoped to ``unittest`` and ``coverage``.
12
+ If your project requires ``pytest``-specific features (fixtures, parametrize,
13
+ plugins, parallel execution), install ``pytest`` directly or via
14
+ ``core-dev-tools`` and invoke it standalone — it is a better fit for that use
15
+ case than routing it through this abstraction layer.
9
16
 
10
17
  ===============================================================================
11
18
 
@@ -40,32 +47,35 @@ Install from PyPI using pip:
40
47
  .. code-block:: bash
41
48
 
42
49
  pip install core-tests
43
-
44
- Or using uv:
45
-
46
- .. code-block:: bash
47
-
48
- uv pip install core-tests
50
+ uv pip install core-tests # Or using UV...
49
51
 
50
52
 
51
53
  Features
52
54
  ===============================================================================
53
55
 
54
- * **Dual Test Engine Support**: Run tests using either `unittest` or `pytest` frameworks
55
- * **Flexible Test Discovery**: Supports multiple file patterns:
56
- - `test_*.py` (standard pattern)
57
- - `*_test.py` (alternative pattern)
58
- - `tests_*.py` (custom pattern)
59
- * **Custom Pattern Support**: Specify custom file patterns using the `--pattern` flag
60
- * **Test Organization**: Run tests by type (unit, integration, functional, etc.)
61
- * **Coverage Reports**: Generate coverage reports with both frameworks
62
- * **CLI Integration**: Easy integration via Click command collections
56
+ * **Unified CLI abstraction**: Expose ``run-tests`` and ``run-coverage`` in any
57
+ project without duplicating boilerplate — just wire ``cli_tests`` into your
58
+ ``CommandCollection``.
59
+ * **Flexible Test Discovery**: Supports multiple file patterns out of the box:
60
+
61
+ - ``test_*.py`` (standard pattern)
62
+ - ``*_test.py`` (alternative pattern)
63
+ - ``tests_*.py`` (custom pattern)
64
+
65
+ * **Custom Pattern Support**: Override discovery with ``--pattern`` for
66
+ non-standard file layouts.
67
+ * **Test Organization**: Target specific test directories (unit, integration,
68
+ functional, etc.) via ``--test-type``.
69
+ * **Branch Coverage Reports**: Generate branch-level coverage reports and
70
+ optional HTML output.
71
+ * **DRY principle**: One implementation shared across all projects in the
72
+ ecosystem.
63
73
 
64
74
 
65
75
  How to Use
66
76
  ===============================================================================
67
77
 
68
- Create a ``manager.py`` file in your project root to integrate
78
+ Create a ``manager.py`` file in your project root to integrate
69
79
  the test commands:
70
80
 
71
81
  .. code-block:: python
@@ -80,7 +90,7 @@ the test commands:
80
90
 
81
91
  This setup provides two commands:
82
92
 
83
- * ``run-tests``: Execute test suites with unittest or pytest
93
+ * ``run-tests``: Execute unittest-based test suites
84
94
  * ``run-coverage``: Generate code coverage reports
85
95
 
86
96
  Example usage:
@@ -88,7 +98,7 @@ Example usage:
88
98
  .. code-block:: bash
89
99
 
90
100
  python manager.py run-tests --test-type unit
91
- python manager.py run-coverage --engine pytest
101
+ python manager.py run-coverage
92
102
 
93
103
 
94
104
  Available Commands
@@ -97,49 +107,48 @@ Available Commands
97
107
  run-tests
98
108
  -------------------------------------------------------------------------------
99
109
 
100
- Execute test suites with flexible options:
110
+ Execute unittest-based test suites with flexible options:
101
111
 
102
112
  **Options:**
103
113
 
104
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
105
- * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``, ``integration``, ``functional``)
106
- * ``--pattern``: File pattern to match test files (e.g., ``*.py``, ``test_*.py``). Works with both engines.
114
+ * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``,
115
+ ``integration``, ``functional``). Default: ``unit``
116
+ * ``--pattern``: File pattern to match test files (e.g., ``*.py``,
117
+ ``test_*.py``). Defaults to multi-pattern discovery.
107
118
 
108
119
  **Examples:**
109
120
 
110
121
  .. code-block:: bash
111
122
 
112
- # Run unit tests with unittest (default)
123
+ # Run unit tests (default)
113
124
  python manager.py run-tests --test-type unit
114
125
 
115
- # Run integration tests with pytest
116
- python manager.py run-tests --engine pytest --test-type integration
126
+ # Run integration tests
127
+ python manager.py run-tests --test-type integration
117
128
 
118
- # Run tests with custom pattern
119
- python manager.py run-tests --test-type functional --pattern "test_*.py"
129
+ # Run tests with a custom file pattern
130
+ python manager.py run-tests --test-type functional --pattern "*.py"
120
131
 
121
- # Run all tests in a custom folder
132
+ # Run tests in a custom folder
122
133
  python manager.py run-tests --test-type "custom_folder"
123
134
 
124
135
 
125
136
  run-coverage
126
137
  -------------------------------------------------------------------------------
127
138
 
128
- Generate code coverage reports:
139
+ Generate code coverage reports across all test directories:
129
140
 
130
141
  **Options:**
131
142
 
132
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
143
+ * ``--save-report``: Save HTML and data coverage reports to disk.
144
+ Default: ``True``
133
145
 
134
146
  **Examples:**
135
147
 
136
148
  .. code-block:: bash
137
149
 
138
- # Generate coverage with unittest
139
150
  python manager.py run-coverage
140
-
141
- # Generate coverage with pytest
142
- python manager.py run-coverage --engine pytest
151
+ python manager.py run-coverage --save-report false
143
152
 
144
153
 
145
154
  Quick Start
@@ -181,78 +190,32 @@ Tests and Coverage
181
190
 
182
191
  python manager.py run-tests --test-type unit
183
192
  python manager.py run-tests --test-type integration
184
- python manager.py run-tests --test-type "another folder that contains test cases under ./tests"
185
193
  python manager.py run-tests --test-type functional --pattern "*.py"
194
+ python manager.py run-coverage
186
195
 
187
196
 
188
- Using PyTest
197
+ Using pytest directly
189
198
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
190
199
 
191
- The `unittest` framework cannot discover or run pytest-style tests, it is designed to
192
- discover and run tests that are subclasses of `unittest.TestCase` and follow its
193
- conventions. Pytest-style tests (i.e., functions named test_* that are not inside a
194
- `unittest.TestCase` class, or tests using pytest fixtures, parametrize, etc.) are not
195
- recognized by unittest's discovery mechanism, `unittest` will simply ignore standalone
196
- test functions and any pytest-specific features...
197
-
198
- That's why you can use PyTest if required.
200
+ ``unittest`` cannot discover standalone ``test_*`` functions or use pytest
201
+ fixtures. If your project relies on those features, invoke ``pytest`` directly:
199
202
 
200
203
  .. code-block:: bash
201
204
 
202
- python manager.py run-tests --engine pytest
205
+ pytest tests/unit/
206
+ pytest -n auto --cov=your_package --cov-report=html
203
207
 
204
- ..
205
-
206
- Test coverage
207
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
208
+ Install ``pytest`` via ``pip`` or through ``core-dev-tools``:
208
209
 
209
210
  .. code-block:: bash
210
211
 
211
- python manager.py run-coverage # For `unittest` framework...
212
- python manager.py run-coverage --engine pytest # For `PyTest`...
213
- pytest -n auto --cov=core_tests --cov-report=html # Direct `pytest` execution...
212
+ pip install pytest pytest-xdist pytest-cov
213
+ # or
214
+ pip install ".[dev]" # if core-dev-tools includes pytest
214
215
 
215
216
  ..
216
217
 
217
218
 
218
- Best Practices
219
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
220
-
221
- When working with pytest, consider these optimization strategies:
222
-
223
- 1. **Use parallel execution for independent tests:**
224
-
225
- .. code-block:: bash
226
-
227
- pytest -n auto
228
-
229
- ..
230
-
231
- 2. **Run fast unit tests first during development:**
232
-
233
- .. code-block:: bash
234
-
235
- pytest tests/unit/ -n auto
236
-
237
- ..
238
-
239
- 3. **Run functional tests with limited parallelism:**
240
-
241
- .. code-block:: bash
242
-
243
- pytest tests/functional/ -n 2 # Avoid AWS rate limits
244
-
245
- ..
246
-
247
- 4. **Use markers to run specific test subsets:**
248
-
249
- .. code-block:: bash
250
-
251
- pytest -m "unit and not slow" -n auto
252
-
253
- ..
254
-
255
-
256
219
  Contributing
257
220
  ===============================================================================
258
221
 
@@ -261,7 +224,7 @@ Contributions are welcome! Please:
261
224
  1. Fork the repository
262
225
  2. Create a feature branch
263
226
  3. Write tests for new functionality
264
- 4. Ensure all tests pass: ``pytest -n auto``
227
+ 4. Ensure all tests pass: ``python manager.py run-tests --test-type unit``
265
228
  5. Run linting: ``pylint core_tests``
266
229
  6. Run security checks: ``bandit -r core_tests``
267
230
  7. Submit a pull request
@@ -292,4 +255,4 @@ For questions or support, please open an issue on GitLab or contact the maintain
292
255
  Authors
293
256
  ===============================================================================
294
257
 
295
- * **Alejandro Cora González** - *Initial work* - alek.cora.glez@gmail.com
258
+ * **Alejandro Cora González** - *Initial work* - alek.cora.glez@gmail.com
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ Provides common elements for testing purposes.
5
+ """
6
+
7
+ from importlib.metadata import PackageNotFoundError
8
+ from importlib.metadata import version
9
+
10
+ from core_tests.tests.base import BaseTestCase
11
+ from core_tests.tests.runner import cli_tests
12
+
13
+ try:
14
+ __version__ = version("core-tests")
15
+
16
+ except PackageNotFoundError:
17
+ __version__ = "unknown"
18
+
19
+
20
+ __all__ = [
21
+ "__version__",
22
+ "BaseTestCase",
23
+ "cli_tests",
24
+ ]
@@ -0,0 +1,153 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ This module provides a group of CLI commands that abstract unittest-based
5
+ test execution and code coverage measurement. Consuming projects import
6
+ ``cli_tests`` and wire it into their own ``CommandCollection`` to expose
7
+ ``run-tests`` and ``run-coverage`` without duplicating this logic.
8
+
9
+ This library is intentionally scoped to ``unittest`` and ``coverage``. If your
10
+ project requires pytest-specific features (fixtures, parametrize, plugins),
11
+ install ``pytest`` directly or via ``core-dev-tools`` and invoke it standalone.
12
+
13
+ **Test File Discovery:**
14
+
15
+ By default, (``tests_*.py``), ``run-tests`` runs discovery across all three
16
+ built-in patterns: ``test_*.py``, ``*_test.py``, and ``tests_*.py``.
17
+ Supply ``--pattern`` with any other glob to target a specific naming
18
+ convention instead.
19
+
20
+ Tests that connect to real external services should use a naming convention
21
+ that falls outside these patterns (e.g. ``check_*.py``) so they are not
22
+ picked up automatically.
23
+
24
+ **Available Commands:**
25
+
26
+ * ``python manager.py run-tests``
27
+ * ``python manager.py run-tests --test-type unit``
28
+ * ``python manager.py run-tests --test-type integration``
29
+ * ``python manager.py run-tests --test-type functional --pattern "*.py"``
30
+ * ``python manager.py run-coverage``
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import logging
36
+ import os
37
+ import sys
38
+ import typing
39
+ from unittest import TestCase
40
+ from unittest import TestLoader
41
+ from unittest import TestSuite
42
+ from unittest import TextTestRunner
43
+
44
+ from click import echo, option
45
+ from click.decorators import group
46
+ from coverage import coverage, CoverageException
47
+
48
+ patterns = [
49
+ "test_*.py",
50
+ "*_test.py",
51
+ "tests_*.py",
52
+ ]
53
+
54
+
55
+ @group()
56
+ def cli_tests():
57
+ """
58
+ Group of commands related to tests.
59
+ """
60
+
61
+
62
+ @cli_tests.command("run-tests")
63
+ @option("-t", "--test-type", "test_type", default="unit")
64
+ @option("-p", "--pattern", "pattern", default="tests_*.py")
65
+ def run_tests(test_type: str, pattern: str) -> None:
66
+ """
67
+ Runs unittest-based tests in a specific directory.
68
+
69
+ :param test_type: Directory name under ./tests/ (e.g., 'unit', 'integration', 'functional').
70
+ :param pattern: File glob pattern passed to ``TestLoader.discover``.
71
+
72
+ Pattern Usage:
73
+ - Default ``tests_*.py`` runs discovery across all three built-in
74
+ patterns: ``test_*.py``, ``*_test.py``, and ``tests_*.py``.
75
+ - Any other glob (e.g. ``test*.py``, ``*_test.py``, ``*.py``) runs a
76
+ single ``TestLoader.discover`` call with that pattern.
77
+ """
78
+
79
+ if not os.path.exists(f"./tests/{test_type}"):
80
+ echo(f"The directory: {test_type} does not exist under ./tests!", err=True)
81
+ sys.exit(1)
82
+
83
+ if test_type == "unit":
84
+ # Just removing verbosity from unit tests...
85
+ level = os.getenv("LOGGER_LEVEL_FOR_TEST", str(logging.ERROR))
86
+ os.environ["LOGGER_LEVEL"] = level
87
+
88
+ all_tests: typing.List[TestCase | TestSuite] = []
89
+
90
+ if pattern != "tests_*.py":
91
+ tests = TestLoader().discover(f"./tests/{test_type}", pattern=pattern)
92
+ all_tests.extend(tests)
93
+
94
+ else:
95
+ for pattern_glob in patterns:
96
+ tests = TestLoader().discover(f"./tests/{test_type}", pattern=pattern_glob)
97
+ all_tests.extend(tests)
98
+
99
+ result = TextTestRunner(verbosity=2).run(TestSuite(all_tests))
100
+ if not result.wasSuccessful():
101
+ sys.exit(1)
102
+
103
+
104
+ @cli_tests.command("run-coverage")
105
+ @option("-s", "--save-report", "save_report", default=True)
106
+ def run_coverage(save_report: bool) -> None:
107
+ """
108
+ Runs all tests across all test directories and generates a coverage report.
109
+
110
+ :param save_report: Whether to save HTML and data coverage reports to disk.
111
+ :type save_report: bool
112
+
113
+ Coverage Analysis:
114
+ - Runs tests with branch coverage enabled.
115
+ - Analyzes all source files in current directory.
116
+ - Generates console report summary.
117
+ - Optionally saves HTML report (default: True).
118
+
119
+ File Discovery:
120
+ Automatically finds files matching: ``test_*.py``, ``*_test.py``, ``tests_*.py``
121
+ across all subdirectories under ``./tests/``. It means that functional or integration
122
+ tests that connect to real services should be named with other pattern,
123
+ like ``check_aws_integration``.
124
+ """
125
+
126
+ os.environ["LOGGER_LEVEL"] = os.getenv("LOGGER_LEVEL_FOR_TEST", str(logging.ERROR))
127
+ coverage_ = coverage(branch=True, source=["."])
128
+ coverage_.start()
129
+
130
+ all_tests: typing.List[TestCase | TestSuite] = []
131
+ for pattern_glob in patterns:
132
+ tests = TestLoader().discover("./tests", pattern=pattern_glob)
133
+ all_tests.extend(tests)
134
+
135
+ result = TextTestRunner(verbosity=3).run(TestSuite(all_tests))
136
+ if not result.wasSuccessful():
137
+ sys.exit(1)
138
+
139
+ coverage_.stop()
140
+
141
+ try:
142
+ echo("Coverage Summary:")
143
+ coverage_.report()
144
+
145
+ if save_report:
146
+ coverage_.save()
147
+ coverage_.html_report()
148
+
149
+ coverage_.erase()
150
+
151
+ except CoverageException as error:
152
+ echo(error)
153
+ sys.exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-tests
3
- Version: 2.0.4
3
+ Version: 2.1.0
4
4
  Summary: It contains common elements for testing purposes...
5
5
  Author-email: Alejandro Cora González <alek.cora.glez@gmail.com>
6
6
  Maintainer: Alejandro Cora González
@@ -22,26 +22,33 @@ Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
25
27
  Requires-Python: >=3.9
26
28
  Description-Content-Type: text/x-rst
27
29
  License-File: LICENSE
28
30
  Requires-Dist: click>=8.1.8
29
31
  Requires-Dist: coverage>=7.7.1
30
32
  Requires-Dist: environs>=14.1.1
31
- Requires-Dist: pytest>=7.4.0
32
- Requires-Dist: pytest-xdist>=3.5.0
33
33
  Provides-Extra: dev
34
- Requires-Dist: core-dev-tools>=1.0.1; extra == "dev"
34
+ Requires-Dist: core-dev-tools>=2.0.0; extra == "dev"
35
35
  Dynamic: license-file
36
36
 
37
37
  core-tests
38
38
  ===============================================================================
39
39
 
40
- This project contains basic elements for testing purposes and the ability
41
- to run (via console commands) tests and code coverage (unittest-based). This way, we can
42
- stick to the `DRY -- Don't Repeat Yourself` principle and avoid code duplication
43
- in each python project where tests coverage and tests execution are
44
- expected...
40
+ A reusable library that provides CLI commands for running ``unittest``-based
41
+ tests and generating code coverage reports. It wraps Python's built-in
42
+ ``unittest`` framework and ``coverage`` into a ``Click`` command group so
43
+ consuming projects can use ``python manager.py run-tests`` and
44
+ ``python manager.py run-coverage`` without duplicating that logic across
45
+ every project in the ecosystem.
46
+
47
+ This library is intentionally scoped to ``unittest`` and ``coverage``.
48
+ If your project requires ``pytest``-specific features (fixtures, parametrize,
49
+ plugins, parallel execution), install ``pytest`` directly or via
50
+ ``core-dev-tools`` and invoke it standalone — it is a better fit for that use
51
+ case than routing it through this abstraction layer.
45
52
 
46
53
  ===============================================================================
47
54
 
@@ -76,32 +83,35 @@ Install from PyPI using pip:
76
83
  .. code-block:: bash
77
84
 
78
85
  pip install core-tests
79
-
80
- Or using uv:
81
-
82
- .. code-block:: bash
83
-
84
- uv pip install core-tests
86
+ uv pip install core-tests # Or using UV...
85
87
 
86
88
 
87
89
  Features
88
90
  ===============================================================================
89
91
 
90
- * **Dual Test Engine Support**: Run tests using either `unittest` or `pytest` frameworks
91
- * **Flexible Test Discovery**: Supports multiple file patterns:
92
- - `test_*.py` (standard pattern)
93
- - `*_test.py` (alternative pattern)
94
- - `tests_*.py` (custom pattern)
95
- * **Custom Pattern Support**: Specify custom file patterns using the `--pattern` flag
96
- * **Test Organization**: Run tests by type (unit, integration, functional, etc.)
97
- * **Coverage Reports**: Generate coverage reports with both frameworks
98
- * **CLI Integration**: Easy integration via Click command collections
92
+ * **Unified CLI abstraction**: Expose ``run-tests`` and ``run-coverage`` in any
93
+ project without duplicating boilerplate — just wire ``cli_tests`` into your
94
+ ``CommandCollection``.
95
+ * **Flexible Test Discovery**: Supports multiple file patterns out of the box:
96
+
97
+ - ``test_*.py`` (standard pattern)
98
+ - ``*_test.py`` (alternative pattern)
99
+ - ``tests_*.py`` (custom pattern)
100
+
101
+ * **Custom Pattern Support**: Override discovery with ``--pattern`` for
102
+ non-standard file layouts.
103
+ * **Test Organization**: Target specific test directories (unit, integration,
104
+ functional, etc.) via ``--test-type``.
105
+ * **Branch Coverage Reports**: Generate branch-level coverage reports and
106
+ optional HTML output.
107
+ * **DRY principle**: One implementation shared across all projects in the
108
+ ecosystem.
99
109
 
100
110
 
101
111
  How to Use
102
112
  ===============================================================================
103
113
 
104
- Create a ``manager.py`` file in your project root to integrate
114
+ Create a ``manager.py`` file in your project root to integrate
105
115
  the test commands:
106
116
 
107
117
  .. code-block:: python
@@ -116,7 +126,7 @@ the test commands:
116
126
 
117
127
  This setup provides two commands:
118
128
 
119
- * ``run-tests``: Execute test suites with unittest or pytest
129
+ * ``run-tests``: Execute unittest-based test suites
120
130
  * ``run-coverage``: Generate code coverage reports
121
131
 
122
132
  Example usage:
@@ -124,7 +134,7 @@ Example usage:
124
134
  .. code-block:: bash
125
135
 
126
136
  python manager.py run-tests --test-type unit
127
- python manager.py run-coverage --engine pytest
137
+ python manager.py run-coverage
128
138
 
129
139
 
130
140
  Available Commands
@@ -133,49 +143,48 @@ Available Commands
133
143
  run-tests
134
144
  -------------------------------------------------------------------------------
135
145
 
136
- Execute test suites with flexible options:
146
+ Execute unittest-based test suites with flexible options:
137
147
 
138
148
  **Options:**
139
149
 
140
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
141
- * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``, ``integration``, ``functional``)
142
- * ``--pattern``: File pattern to match test files (e.g., ``*.py``, ``test_*.py``). Works with both engines.
150
+ * ``--test-type``: Folder name under ``./tests`` directory (e.g., ``unit``,
151
+ ``integration``, ``functional``). Default: ``unit``
152
+ * ``--pattern``: File pattern to match test files (e.g., ``*.py``,
153
+ ``test_*.py``). Defaults to multi-pattern discovery.
143
154
 
144
155
  **Examples:**
145
156
 
146
157
  .. code-block:: bash
147
158
 
148
- # Run unit tests with unittest (default)
159
+ # Run unit tests (default)
149
160
  python manager.py run-tests --test-type unit
150
161
 
151
- # Run integration tests with pytest
152
- python manager.py run-tests --engine pytest --test-type integration
162
+ # Run integration tests
163
+ python manager.py run-tests --test-type integration
153
164
 
154
- # Run tests with custom pattern
155
- python manager.py run-tests --test-type functional --pattern "test_*.py"
165
+ # Run tests with a custom file pattern
166
+ python manager.py run-tests --test-type functional --pattern "*.py"
156
167
 
157
- # Run all tests in a custom folder
168
+ # Run tests in a custom folder
158
169
  python manager.py run-tests --test-type "custom_folder"
159
170
 
160
171
 
161
172
  run-coverage
162
173
  -------------------------------------------------------------------------------
163
174
 
164
- Generate code coverage reports:
175
+ Generate code coverage reports across all test directories:
165
176
 
166
177
  **Options:**
167
178
 
168
- * ``--engine``: Test engine to use (``unittest`` or ``pytest``). Default: ``unittest``
179
+ * ``--save-report``: Save HTML and data coverage reports to disk.
180
+ Default: ``True``
169
181
 
170
182
  **Examples:**
171
183
 
172
184
  .. code-block:: bash
173
185
 
174
- # Generate coverage with unittest
175
186
  python manager.py run-coverage
176
-
177
- # Generate coverage with pytest
178
- python manager.py run-coverage --engine pytest
187
+ python manager.py run-coverage --save-report false
179
188
 
180
189
 
181
190
  Quick Start
@@ -217,78 +226,32 @@ Tests and Coverage
217
226
 
218
227
  python manager.py run-tests --test-type unit
219
228
  python manager.py run-tests --test-type integration
220
- python manager.py run-tests --test-type "another folder that contains test cases under ./tests"
221
229
  python manager.py run-tests --test-type functional --pattern "*.py"
230
+ python manager.py run-coverage
222
231
 
223
232
 
224
- Using PyTest
233
+ Using pytest directly
225
234
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
226
235
 
227
- The `unittest` framework cannot discover or run pytest-style tests, it is designed to
228
- discover and run tests that are subclasses of `unittest.TestCase` and follow its
229
- conventions. Pytest-style tests (i.e., functions named test_* that are not inside a
230
- `unittest.TestCase` class, or tests using pytest fixtures, parametrize, etc.) are not
231
- recognized by unittest's discovery mechanism, `unittest` will simply ignore standalone
232
- test functions and any pytest-specific features...
233
-
234
- That's why you can use PyTest if required.
236
+ ``unittest`` cannot discover standalone ``test_*`` functions or use pytest
237
+ fixtures. If your project relies on those features, invoke ``pytest`` directly:
235
238
 
236
239
  .. code-block:: bash
237
240
 
238
- python manager.py run-tests --engine pytest
241
+ pytest tests/unit/
242
+ pytest -n auto --cov=your_package --cov-report=html
239
243
 
240
- ..
241
-
242
- Test coverage
243
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
244
+ Install ``pytest`` via ``pip`` or through ``core-dev-tools``:
244
245
 
245
246
  .. code-block:: bash
246
247
 
247
- python manager.py run-coverage # For `unittest` framework...
248
- python manager.py run-coverage --engine pytest # For `PyTest`...
249
- pytest -n auto --cov=core_tests --cov-report=html # Direct `pytest` execution...
248
+ pip install pytest pytest-xdist pytest-cov
249
+ # or
250
+ pip install ".[dev]" # if core-dev-tools includes pytest
250
251
 
251
252
  ..
252
253
 
253
254
 
254
- Best Practices
255
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
256
-
257
- When working with pytest, consider these optimization strategies:
258
-
259
- 1. **Use parallel execution for independent tests:**
260
-
261
- .. code-block:: bash
262
-
263
- pytest -n auto
264
-
265
- ..
266
-
267
- 2. **Run fast unit tests first during development:**
268
-
269
- .. code-block:: bash
270
-
271
- pytest tests/unit/ -n auto
272
-
273
- ..
274
-
275
- 3. **Run functional tests with limited parallelism:**
276
-
277
- .. code-block:: bash
278
-
279
- pytest tests/functional/ -n 2 # Avoid AWS rate limits
280
-
281
- ..
282
-
283
- 4. **Use markers to run specific test subsets:**
284
-
285
- .. code-block:: bash
286
-
287
- pytest -m "unit and not slow" -n auto
288
-
289
- ..
290
-
291
-
292
255
  Contributing
293
256
  ===============================================================================
294
257
 
@@ -297,7 +260,7 @@ Contributions are welcome! Please:
297
260
  1. Fork the repository
298
261
  2. Create a feature branch
299
262
  3. Write tests for new functionality
300
- 4. Ensure all tests pass: ``pytest -n auto``
263
+ 4. Ensure all tests pass: ``python manager.py run-tests --test-type unit``
301
264
  5. Run linting: ``pylint core_tests``
302
265
  6. Run security checks: ``bandit -r core_tests``
303
266
  7. Submit a pull request
@@ -0,0 +1,6 @@
1
+ click>=8.1.8
2
+ coverage>=7.7.1
3
+ environs>=14.1.1
4
+
5
+ [dev]
6
+ core-dev-tools>=2.0.0
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "core-tests"
11
- version = "2.0.4"
11
+ version = "2.1.0"
12
12
 
13
13
  description = """It contains common elements for testing purposes..."""
14
14
 
@@ -38,19 +38,19 @@ classifiers = [
38
38
  "Programming Language :: Python :: 3.11",
39
39
  "Programming Language :: Python :: 3.12",
40
40
  "Programming Language :: Python :: 3.13",
41
+ "Programming Language :: Python :: 3.14",
42
+ "Programming Language :: Python :: Implementation :: PyPy",
41
43
  ]
42
44
 
43
45
  dependencies = [
44
46
  "click>=8.1.8",
45
47
  "coverage>=7.7.1",
46
48
  "environs>=14.1.1",
47
- "pytest>=7.4.0",
48
- "pytest-xdist>=3.5.0",
49
49
  ]
50
50
 
51
51
  [project.optional-dependencies]
52
52
  dev = [
53
- "core-dev-tools>=1.0.1",
53
+ "core-dev-tools>=2.0.0",
54
54
  ]
55
55
 
56
56
  [project.urls]
@@ -60,5 +60,8 @@ Documentation = "https://core-tests.readthedocs.io/en/latest/"
60
60
  Issues = "https://gitlab.com/bytecode-solutions/core/core-tests/-/issues"
61
61
  Changelog = "https://gitlab.com/bytecode-solutions/core/core-tests/-/blob/master/CHANGELOG.md"
62
62
 
63
+ [tool.pytest.ini_options]
64
+ python_files = ["test_*.py", "*_test.py", "tests_*.py"]
65
+
63
66
  [tool.setuptools.package-data]
64
67
  "core_tests" = ["py.typed"]
File without changes
@@ -1,226 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """
4
- This module provides a group of commands related to tests, this way we
5
- avoid defining them in each project that requires them.
6
-
7
- **Test File Discovery:**
8
-
9
- Automatically discovers test files matching these patterns:
10
- * ``test_*.py`` (standard pytest/unittest pattern)
11
- * ``*_test.py`` (standard pytest pattern)
12
- * ``tests_*.py`` (legacy pattern support)
13
-
14
- Available Commands:
15
- * python manager.py run-tests --test-type unit
16
- * python manager.py run-tests --test-type integration
17
- * python manager.py run-tests --test-type functional
18
- * python manager.py run-tests --engine pytest
19
- * python manager.py run-tests --pattern "test_specific"
20
- * python manager.py run-coverage
21
- * python manager.py run-coverage --engine pytest
22
- """
23
-
24
- from __future__ import annotations
25
-
26
- import glob
27
- import logging
28
- import os
29
- import sys
30
- import typing
31
- from unittest import TestCase
32
- from unittest import TestLoader
33
- from unittest import TestSuite
34
- from unittest import TextTestRunner
35
-
36
- import pytest
37
- from click import echo, option
38
- from click.decorators import group
39
- from coverage import coverage, CoverageException
40
-
41
- patterns = [
42
- "test_*.py",
43
- "*_test.py",
44
- "tests_*.py",
45
- ]
46
-
47
-
48
- @group()
49
- def cli_tests():
50
- """
51
- Group of commands related to tests.
52
- """
53
-
54
-
55
- @cli_tests.command("run-tests")
56
- @option("-t", "--test-type", "test_type", default="unit")
57
- @option("-p", "--pattern", "pattern", default="tests*.py")
58
- @option("-e", "--engine", "engine", default="unittest")
59
- def run_tests(test_type: str, pattern: str, engine: str) -> None:
60
- """
61
- Runs tests in a specific directory using the specified engine.
62
-
63
- :param test_type: Directory name under ./tests/ (e.g., 'unit', 'integration').
64
- :param pattern: File pattern for discovery or test name pattern for filtering.
65
- :param engine: Test engine to use ('unittest' or 'pytest').
66
-
67
- File Discovery:
68
- Automatically finds files matching: `test_*.py`, `*_test.py`, `tests_*.py`.
69
-
70
- Pattern Usage:
71
- - File patterns (*.py): Used for file discovery (pytest only).
72
- - Test names: Used with -k option for test filtering (pytest only).
73
- - Default: 'tests*.py' (backward compatibility).
74
- """
75
-
76
- validate_engines(engine)
77
- if not os.path.exists(f"./tests/{test_type}"):
78
- echo(f"The directory: {test_type} does not exist under ./tests!", err=True)
79
- sys.exit(1)
80
-
81
- if test_type == "unit":
82
- # Just removing verbosity from unit tests...
83
- level = os.getenv("LOGGER_LEVEL_FOR_TEST", str(logging.ERROR))
84
- os.environ["LOGGER_LEVEL"] = level
85
-
86
- if engine == "pytest":
87
- test_path = f"./tests/{test_type}"
88
-
89
- # Determine if pattern is for file discovery or test filtering
90
- is_file_pattern = "*" in pattern and pattern.endswith(".py")
91
-
92
- # Find all test files using appropriate patterns
93
- test_files = []
94
- if is_file_pattern and pattern != "tests_*.py":
95
- # Use custom file pattern for discovery
96
- test_files.extend(glob.glob(f"{test_path}/{pattern}"))
97
-
98
- else:
99
- # Use default patterns for file discovery
100
- for pattern_glob in patterns:
101
- test_files.extend(glob.glob(f"{test_path}/{pattern_glob}"))
102
-
103
- if not test_files:
104
- echo(f"No test files found in {test_path}", err=True)
105
- sys.exit(1)
106
-
107
- # Use specific test files instead of directory discovery
108
- args = test_files + ["-v"]
109
-
110
- # If pattern is for test name filtering (not file pattern), use -k
111
- if not is_file_pattern and pattern != "tests_*.py":
112
- args.extend(["-k", pattern])
113
-
114
- exit_code = pytest.main(args)
115
- if exit_code != 0:
116
- sys.exit(exit_code)
117
-
118
- else:
119
- # Determine if pattern is for file discovery or test filtering
120
- is_file_pattern = "*" in pattern and pattern.endswith(".py")
121
-
122
- # Use the same patterns as pytest for consistency
123
- all_tests: typing.List[TestCase | TestSuite] = []
124
- if is_file_pattern and pattern != "tests_*.py":
125
- # Use custom file pattern for discovery
126
- tests = TestLoader().discover(f"./tests/{test_type}", pattern=pattern)
127
- all_tests.extend(tests)
128
- else:
129
- # Use default patterns for file discovery
130
- for pattern_glob in patterns:
131
- tests = TestLoader().discover(f"./tests/{test_type}", pattern=pattern_glob)
132
- all_tests.extend(tests)
133
-
134
- # Combine all discovered tests into a single suite
135
- combined_suite = TestSuite(all_tests)
136
- result = TextTestRunner(verbosity=2).run(combined_suite)
137
- if not result.wasSuccessful():
138
- sys.exit(1)
139
-
140
-
141
- @cli_tests.command("run-coverage")
142
- @option("-s", "--save-report", "save_report", default=True)
143
- @option("-e", "--engine", "engine", default="unittest")
144
- def run_coverage(save_report: bool, engine: str) -> None:
145
- """
146
- Runs all tests across all test directories and generates a coverage report.
147
-
148
- :param save_report: Whether to save HTML and data coverage reports to disk.
149
- :type save_report: bool
150
- :param engine: Test engine to use ('unittest' or 'pytest').
151
- :type engine: str
152
-
153
- Coverage Analysis:
154
- - Runs tests with branch coverage enabled.
155
- - Analyzes all source files in current directory.
156
- - Generates console report summary.
157
- - Optionally saves HTML report (default: True).
158
-
159
- File Discovery:
160
- Automatically finds files matching: `test_*.py`, `*_test.py`, `tests_*.py`.
161
- across all subdirectories under `./tests/`.
162
- """
163
-
164
- validate_engines(engine)
165
- os.environ["LOGGER_LEVEL"] = os.getenv("LOGGER_LEVEL_FOR_TEST", str(logging.ERROR))
166
- coverage_ = coverage(branch=True, source=["."])
167
- coverage_.start()
168
-
169
- if engine == "pytest":
170
- # Finding all test files using multiple patterns
171
- # across all test directories...
172
- test_files = []
173
- for pattern_glob in patterns:
174
- test_files.extend(glob.glob(f"./tests/**/{pattern_glob}", recursive=True))
175
-
176
- if test_files:
177
- exit_code = pytest.main(test_files + ["-v"])
178
- else:
179
- exit_code = pytest.main(["./tests", "-v"])
180
-
181
- if exit_code != 0:
182
- sys.exit(exit_code)
183
-
184
- else:
185
- all_tests: typing.List[TestCase | TestSuite] = []
186
- for pattern_glob in patterns:
187
- tests = TestLoader().discover("./tests", pattern=pattern_glob)
188
- all_tests.extend(tests)
189
-
190
- result = TextTestRunner(verbosity=3).run(TestSuite(all_tests))
191
- if not result.wasSuccessful():
192
- sys.exit(1)
193
-
194
- coverage_.stop()
195
-
196
- try:
197
- echo("Coverage Summary:")
198
- coverage_.report()
199
-
200
- if save_report:
201
- coverage_.save()
202
- coverage_.html_report()
203
-
204
- coverage_.erase()
205
-
206
- except CoverageException as error:
207
- echo(error)
208
- sys.exit(1)
209
-
210
-
211
- def validate_engines(engine: str) -> None:
212
- """
213
- Validates that the specified test engine is supported.
214
-
215
- :param engine: The test engine name to validate.
216
- :raises: SystemExit: If the engine is not in the list of valid engines.
217
-
218
- Supported Engines:
219
- - 'unittest': Python's built-in unittest framework.
220
- - 'pytest': Third-party pytest framework.
221
- """
222
-
223
- _engines = ["unittest", "pytest"]
224
- if engine not in _engines:
225
- echo(f"Valid engines: {_engines}", err=True)
226
- sys.exit(1)
@@ -1,8 +0,0 @@
1
- click>=8.1.8
2
- coverage>=7.7.1
3
- environs>=14.1.1
4
- pytest>=7.4.0
5
- pytest-xdist>=3.5.0
6
-
7
- [dev]
8
- core-dev-tools>=1.0.1
File without changes
File without changes
File without changes