swaggerforge 0.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.
- swaggerforge-0.1.0/LICENSE +21 -0
- swaggerforge-0.1.0/PKG-INFO +99 -0
- swaggerforge-0.1.0/README.md +77 -0
- swaggerforge-0.1.0/pyproject.toml +41 -0
- swaggerforge-0.1.0/setup.cfg +4 -0
- swaggerforge-0.1.0/src/swaggerforge/__init__.py +0 -0
- swaggerforge-0.1.0/src/swaggerforge/__main__.py +0 -0
- swaggerforge-0.1.0/src/swaggerforge/cli.py +67 -0
- swaggerforge-0.1.0/src/swaggerforge/generator.py +441 -0
- swaggerforge-0.1.0/src/swaggerforge/models.py +46 -0
- swaggerforge-0.1.0/src/swaggerforge/output.py +53 -0
- swaggerforge-0.1.0/src/swaggerforge/parser.py +108 -0
- swaggerforge-0.1.0/src/swaggerforge/template.py +116 -0
- swaggerforge-0.1.0/src/swaggerforge/templates/test_file.py.j2 +24 -0
- swaggerforge-0.1.0/src/swaggerforge/validator.py +44 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/PKG-INFO +99 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/SOURCES.txt +24 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/dependency_links.txt +1 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/entry_points.txt +2 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/requires.txt +11 -0
- swaggerforge-0.1.0/src/swaggerforge.egg-info/top_level.txt +1 -0
- swaggerforge-0.1.0/tests/test_generator.py +332 -0
- swaggerforge-0.1.0/tests/test_output.py +46 -0
- swaggerforge-0.1.0/tests/test_parser.py +79 -0
- swaggerforge-0.1.0/tests/test_template.py +73 -0
- swaggerforge-0.1.0/tests/test_validator.py +45 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Viktor Pylypenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: swaggerforge
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Automatic pytest test generation from OpenAPI (Swagger) specifications
|
|
5
|
+
Author: Viktor Pylypenko
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: openapi,swagger,pytest,test generation,api testing
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: click>=8.0
|
|
12
|
+
Requires-Dist: prance>=23.6.21.0
|
|
13
|
+
Requires-Dist: openapi-core>=0.18
|
|
14
|
+
Requires-Dist: openapi-spec-validator>=0.7
|
|
15
|
+
Requires-Dist: jinja2>=3.0
|
|
16
|
+
Requires-Dist: requests>=2.28
|
|
17
|
+
Requires-Dist: jsonschema>=4.0
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=9.0; extra == "dev"
|
|
20
|
+
Requires-Dist: flake8>=7.0; extra == "dev"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# SwaggerForge
|
|
24
|
+
|
|
25
|
+
Automatic pytest test generation from OpenAPI (Swagger) specifications.
|
|
26
|
+
|
|
27
|
+
SwaggerForge is a Python library and command-line tool that reads an OpenAPI
|
|
28
|
+
specification and generates ready-to-run pytest test files - one per resource
|
|
29
|
+
covering positive, negative, boundary, and boolean scenarios grounded in
|
|
30
|
+
established test-design techniques.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Reads OpenAPI 3.x specifications in JSON or YAML
|
|
35
|
+
- Resolves `$ref` references automatically
|
|
36
|
+
- Generates one pytest file per resource tag
|
|
37
|
+
- Produces six scenario types per endpoint where applicable:
|
|
38
|
+
- **Positive** >>> valid request, expects a 2xx response and validates the
|
|
39
|
+
response schema
|
|
40
|
+
- **Missing required field** >>> omits a required field, expects 400
|
|
41
|
+
- **Wrong data type** >>> sends a mistyped field, expects 400/422
|
|
42
|
+
- **Nonexistent resource** >>> requests an unlikely identifier, expects 404
|
|
43
|
+
- **Boundary values** >>> tests values at and just beyond declared
|
|
44
|
+
numeric/length limits (Boundary Value Analysis)
|
|
45
|
+
- **Boolean coverage** >>> exercises both `true` and `false` for boolean fields
|
|
46
|
+
- Deterministic output: the same specification always produces identical tests
|
|
47
|
+
- Generated files use session-scoped pytest fixtures and run with no manual edits
|
|
48
|
+
|
|
49
|
+
## Requirements
|
|
50
|
+
|
|
51
|
+
- Python 3.10 or newer
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install swaggerforge
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
Generate tests from a specification, pointing at the base URL of the API
|
|
62
|
+
under test:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
swaggerforge generate --spec swagger.json --url http://localhost:8080
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This reads `swagger.json`, writes one `test_<resource>.py` file per resource
|
|
69
|
+
tag into the output directory (default: `tests_generated/`), and the files can
|
|
70
|
+
be run immediately:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pytest tests_generated
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Options
|
|
77
|
+
|
|
78
|
+
| Option | Description | Default |
|
|
79
|
+
|------------|----------------------------------------------------|--------------------|
|
|
80
|
+
| `--spec` | Path to the OpenAPI specification (JSON or YAML) | *(required)* |
|
|
81
|
+
| `--url` | Base URL of the API under test | *(required)* |
|
|
82
|
+
| `--output` | Directory for the generated test files | `tests_generated` |
|
|
83
|
+
|
|
84
|
+
## How it works
|
|
85
|
+
|
|
86
|
+
SwaggerForge runs a six-stage pipeline: the specification is validated, parsed
|
|
87
|
+
into an internal model (with `$ref`s resolved), turned into test scenarios
|
|
88
|
+
based on test-design techniques, rendered into pytest code via templates, and
|
|
89
|
+
written to per-resource files.
|
|
90
|
+
|
|
91
|
+
## Limitations
|
|
92
|
+
|
|
93
|
+
- Targets OpenAPI 3.x with JSON request bodies
|
|
94
|
+
- Authentication is not yet handled (planned)
|
|
95
|
+
- Boundary tests require the specification to declare numeric/length constraints
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SwaggerForge
|
|
2
|
+
|
|
3
|
+
Automatic pytest test generation from OpenAPI (Swagger) specifications.
|
|
4
|
+
|
|
5
|
+
SwaggerForge is a Python library and command-line tool that reads an OpenAPI
|
|
6
|
+
specification and generates ready-to-run pytest test files - one per resource
|
|
7
|
+
covering positive, negative, boundary, and boolean scenarios grounded in
|
|
8
|
+
established test-design techniques.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- Reads OpenAPI 3.x specifications in JSON or YAML
|
|
13
|
+
- Resolves `$ref` references automatically
|
|
14
|
+
- Generates one pytest file per resource tag
|
|
15
|
+
- Produces six scenario types per endpoint where applicable:
|
|
16
|
+
- **Positive** >>> valid request, expects a 2xx response and validates the
|
|
17
|
+
response schema
|
|
18
|
+
- **Missing required field** >>> omits a required field, expects 400
|
|
19
|
+
- **Wrong data type** >>> sends a mistyped field, expects 400/422
|
|
20
|
+
- **Nonexistent resource** >>> requests an unlikely identifier, expects 404
|
|
21
|
+
- **Boundary values** >>> tests values at and just beyond declared
|
|
22
|
+
numeric/length limits (Boundary Value Analysis)
|
|
23
|
+
- **Boolean coverage** >>> exercises both `true` and `false` for boolean fields
|
|
24
|
+
- Deterministic output: the same specification always produces identical tests
|
|
25
|
+
- Generated files use session-scoped pytest fixtures and run with no manual edits
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- Python 3.10 or newer
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install swaggerforge
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Generate tests from a specification, pointing at the base URL of the API
|
|
40
|
+
under test:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
swaggerforge generate --spec swagger.json --url http://localhost:8080
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This reads `swagger.json`, writes one `test_<resource>.py` file per resource
|
|
47
|
+
tag into the output directory (default: `tests_generated/`), and the files can
|
|
48
|
+
be run immediately:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pytest tests_generated
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Options
|
|
55
|
+
|
|
56
|
+
| Option | Description | Default |
|
|
57
|
+
|------------|----------------------------------------------------|--------------------|
|
|
58
|
+
| `--spec` | Path to the OpenAPI specification (JSON or YAML) | *(required)* |
|
|
59
|
+
| `--url` | Base URL of the API under test | *(required)* |
|
|
60
|
+
| `--output` | Directory for the generated test files | `tests_generated` |
|
|
61
|
+
|
|
62
|
+
## How it works
|
|
63
|
+
|
|
64
|
+
SwaggerForge runs a six-stage pipeline: the specification is validated, parsed
|
|
65
|
+
into an internal model (with `$ref`s resolved), turned into test scenarios
|
|
66
|
+
based on test-design techniques, rendered into pytest code via templates, and
|
|
67
|
+
written to per-resource files.
|
|
68
|
+
|
|
69
|
+
## Limitations
|
|
70
|
+
|
|
71
|
+
- Targets OpenAPI 3.x with JSON request bodies
|
|
72
|
+
- Authentication is not yet handled (planned)
|
|
73
|
+
- Boundary tests require the specification to declare numeric/length constraints
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "swaggerforge"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Automatic pytest test generation from OpenAPI (Swagger) specifications"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Viktor Pylypenko" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["openapi", "swagger", "pytest", "test generation", "api testing"]
|
|
16
|
+
dependencies = [
|
|
17
|
+
"click>=8.0",
|
|
18
|
+
"prance>=23.6.21.0",
|
|
19
|
+
"openapi-core>=0.18",
|
|
20
|
+
"openapi-spec-validator>=0.7",
|
|
21
|
+
"jinja2>=3.0",
|
|
22
|
+
"requests>=2.28",
|
|
23
|
+
"jsonschema>=4.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
swaggerforge = "swaggerforge.cli:main"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.package-data]
|
|
33
|
+
swaggerforge = ["templates/*"]
|
|
34
|
+
|
|
35
|
+
[tool.pytest.ini_options]
|
|
36
|
+
minversion = "9.0"
|
|
37
|
+
addopts = "--import-mode=importlib"
|
|
38
|
+
testpaths = ["tests"]
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = ["pytest>=9.0", "flake8>=7.0"]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Command-line interface for SwaggerForge."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from swaggerforge.validator import load_and_validate, SpecValidationError
|
|
5
|
+
from swaggerforge.parser import parse_spec, SpecParseError
|
|
6
|
+
from swaggerforge.generator import generate_scenarios
|
|
7
|
+
from swaggerforge.output import write_test_files
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group()
|
|
11
|
+
@click.version_option()
|
|
12
|
+
def main():
|
|
13
|
+
"""SwaggerForge generate pytest tests from OpenAPI specifications."""
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@main.command()
|
|
18
|
+
@click.option(
|
|
19
|
+
"--spec",
|
|
20
|
+
required=True,
|
|
21
|
+
type=click.Path(exists=True),
|
|
22
|
+
help="Path to the OpenAPI specification file (JSON or YAML).",
|
|
23
|
+
)
|
|
24
|
+
@click.option(
|
|
25
|
+
"--url",
|
|
26
|
+
required=True,
|
|
27
|
+
help="Base URL of the API to be tested.",
|
|
28
|
+
)
|
|
29
|
+
@click.option(
|
|
30
|
+
"--output",
|
|
31
|
+
default="tests_generated",
|
|
32
|
+
type=click.Path(),
|
|
33
|
+
help="Directory where generated test files will be written.",
|
|
34
|
+
)
|
|
35
|
+
def generate(spec, url, output):
|
|
36
|
+
"""Generate pytest test files from an OpenAPI specification."""
|
|
37
|
+
click.echo(f"Reading specification: {spec}")
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
spec_dict = load_and_validate(spec)
|
|
41
|
+
except SpecValidationError as error:
|
|
42
|
+
raise click.ClickException(str(error))
|
|
43
|
+
|
|
44
|
+
click.echo("Specification is valid.")
|
|
45
|
+
click.echo(f"API title: {spec_dict['info']['title']}")
|
|
46
|
+
|
|
47
|
+
try:
|
|
48
|
+
endpoints = parse_spec(spec)
|
|
49
|
+
except SpecParseError as error:
|
|
50
|
+
raise click.ClickException(str(error))
|
|
51
|
+
|
|
52
|
+
tags = sorted({endpoint.tag for endpoint in endpoints})
|
|
53
|
+
click.echo(f"Found {len(endpoints)} endpoints across {len(tags)} resources: {', '.join(tags)}")
|
|
54
|
+
|
|
55
|
+
scenarios = generate_scenarios(endpoints)
|
|
56
|
+
click.echo(f"Generated {len(scenarios)} test scenarios.")
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
written = write_test_files(scenarios, url, output)
|
|
60
|
+
except OSError as error:
|
|
61
|
+
raise click.ClickException(
|
|
62
|
+
f"Could not write test files to '{output}': {error}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
click.echo(f"Wrote {len(written)} test file(s) to '{output}':")
|
|
66
|
+
for path in written:
|
|
67
|
+
click.echo(f" - {path}")
|