A practical demonstration of vibe coding a functional Python application and progressively adding traditional software engineering practices around the generated implementation.
This project contains an interactive CLI-driven synthetic Python project generator capable of creating configurable Python source files containing functions, classes, methods, imports, type hints, docstrings, and randomized logic.
The project is then validated using pytest, pytest-cov, Python compilation checks, shell-based testing utilities, and a GitHub Actions CI pipeline with 100% statement coverage enforcement.
For the purposes of this project, vibe coding follows an iterative AI-assisted development workflow:
Idea / Requirements
↓
AI-Generated Implementation
↓
Execute the Software
↓
Observe the Result
↓
Identify Problems
↓
Modify the Implementation
↓
Automated Testing
↓
Continuous Integration
↓
Repeat
Rather than manually implementing every individual piece of source code, the developer focuses on describing the desired behavior, evaluating the generated implementation, and progressively building confidence in its correctness.
The important part is verification.
Generated code should not automatically be assumed to work simply because it was successfully generated or because the application executed without immediately crashing.
This project demonstrates that distinction by taking vibe-coded software and surrounding it with increasingly rigorous automated verification.
generator.py provides an interactive CLI for generating synthetic Python projects.
Run it with:
python generator.pyThe generator asks how the generated project should be configured.
Example:
============================================================
PYTHON SYNTHETIC PROJECT GENERATOR
============================================================
Press Enter to accept any default.
Project name [generated_project]:
Output directory [./output]:
Number of Python files [3]:
Functions per file [3]:
Classes per file [2]:
Methods per class [3]:
Generated file prefix [module]:
Function name prefix [generated_function]:
Class name prefix [GeneratedClass]:
Method name prefix [generated_method]:
Include imports? [Y/n]:
Include docstrings? [Y/n]:
Include type hints? [Y/n]:
Create __init__.py? [Y/n]:
Create main.py? [Y/n]:
Randomize generated function logic? [Y/n]:
Random seed [leave blank for random]:
Pressing Enter accepts the displayed default, allowing a complete project to be generated without manually configuring every option.
The generator currently supports:
- Multiple Python files
- Configurable functions per file
- Configurable classes per file
- Configurable methods per class
- Custom project names
- Custom output directories
- Custom module naming prefixes
- Custom function naming prefixes
- Custom class naming prefixes
- Custom method naming prefixes
- Python type hints
- Generated docstrings
- Default imports
- Custom imports
- Optional
__init__.py - Optional
main.py - Randomized function logic
- Randomized method logic
- Deterministic generation using random seeds
- Python identifier sanitization
- Filename sanitization
- CLI input validation
- Generation summaries
A generated project may look like:
output/
└── generated_project/
├── __init__.py
├── main.py
├── module_1.py
├── module_2.py
└── module_3.py
A generated module may contain code similar to:
from pathlib import Path
from typing import Any
def generated_function_1_1(values: list[float]) -> object:
"""Automatically generated function: generated_function_1_1."""
if not values:
return None
return max(values)
class GeneratedClass1_1:
"""Automatically generated class: GeneratedClass1_1."""
def __init__(self, values: list[float]) -> None:
self.values = values
def generated_method_1_1(self) -> object:
"""Automatically generated method: generated_method_1_1."""
return sum(self.values)
def generated_method_1_2(self) -> object:
"""Automatically generated method: generated_method_1_2."""
return sorted(self.values)The generated source code itself acts as a synthetic software dataset that can be used for automated testing, static analysis, compilation testing, performance testing, CI experimentation, and other development tooling.
Randomized generation can make automated testing difficult because the output changes between executions.
The generator therefore supports a random seed.
For example:
Random seed [leave blank for random]: 100
Using the same configuration and random seed produces the same randomized sequence.
This makes it possible to perform reproducible testing against generated projects.
Conceptually:
Configuration + Seed
↓
Generator
↓
Predictable Output
↓
Regression Testing
Leave the random seed blank when deterministic output is not required.
The project uses pytest for automated testing.
Install the development dependencies:
python -m pip install -r requirements-dev.txtRun the complete test suite:
python -m pytestOr use the included testing scripts:
./scripts/test.shCoverage is measured using pytest-cov.
Run tests with terminal coverage reporting:
./scripts/test_coverage.shEquivalent command:
python -m pytest \
--cov=generator \
--cov-report=term-missingExample output:
Name Stmts Miss Cover
----------------------------------
generator.py 223 0 100%
----------------------------------
TOTAL 223 0 100%
The current test suite achieves:
100% statement coverage of generator.py.
Coverage does not prove that software is completely correct.
Instead, it tells us that every executable statement measured by the coverage tool was executed during the test suite.
The quality and completeness of the assertions remain important.
Generate an interactive HTML coverage report with:
./scripts/test_coverage_html.shOr:
python -m pytest \
--cov=generator \
--cov-report=htmlThe report is generated under:
htmlcov/
On macOS, open it with:
open htmlcov/index.htmlThe HTML report provides a line-by-line visualization of which portions of the source code were executed during testing.
The project can enforce the required coverage percentage automatically.
Run:
./scripts/test_coverage_enforce.shThe underlying command uses:
python -m pytest \
--cov=generator \
--cov-report=term-missing \
--cov-report=xml \
--cov-fail-under=100The command fails if coverage drops below 100%.
This means adding new source code without corresponding test coverage can cause both local verification and CI verification to fail.
Several shell scripts are included for common development workflows.
./scripts/test.shRuns the normal pytest suite.
./scripts/test_verbose.shDisplays additional information for each executed test.
./scripts/test_fast.shRuns pytest with reduced terminal output.
./scripts/test_coverage.shRuns tests and displays coverage directly in the terminal.
./scripts/test_coverage_html.shGenerates the HTML coverage dashboard.
./scripts/test_coverage_enforce.shRequires 100% statement coverage.
./scripts/test_compile.shChecks that the generator and test source files compile successfully.
A specific pytest test can be executed with:
./scripts/test_single.sh tests/test_generator.py::test_sanitize_identifierBefore pushing changes, run:
./scripts/test_all.shThis performs the broader local verification process, including compilation checks, automated tests, and coverage enforcement.
One of the first issues discovered during development was malformed indentation inside generated Python functions.
The generator itself executed successfully and created the requested files.
However, some of those files contained code similar to:
if not values:
return None
return max(values)The generator had therefore technically completed its immediate task of creating files while still producing invalid output.
The corrected output was:
if not values:
return None
return max(values)This demonstrates an important distinction:
Successful execution of the generator does not guarantee correctness of the generated output.
The automated test suite now compiles generated Python files so syntax and indentation problems can be detected automatically.
This turns a manually discovered bug into a permanent regression test.
Continuous integration is provided through GitHub Actions.
The workflow executes when:
- A pull request targets
main - Code is pushed to
main
The CI matrix currently tests:
Python 3.11
Python 3.12
Python 3.13
Each environment:
- Checks out the repository
- Installs the configured Python version
- Upgrades
pip - Installs development dependencies
- Executes pytest
- Measures code coverage
- Displays coverage in the Actions logs
- Enforces 100% statement coverage
- Generates HTML coverage
- Generates XML coverage
- Uploads coverage reports as GitHub Actions artifacts
The CI test command generates three forms of coverage output:
python -m pytest \
--cov=generator \
--cov-report=term-missing \
--cov-report=html \
--cov-report=xml \
--cov-fail-under=100term-missing displays coverage directly inside the GitHub Actions logs.
html generates a browsable line-by-line coverage dashboard.
xml generates:
coverage.xml
which can also be consumed by external coverage and code-quality tooling.
Each Python version uploads its own coverage reports.
Artifacts are named using the corresponding Python version:
coverage-html-python-3.11
coverage-html-python-3.12
coverage-html-python-3.13
coverage-xml-python-3.11
coverage-xml-python-3.12
coverage-xml-python-3.13
Coverage artifacts are retained for 14 days.
After a workflow finishes:
GitHub Repository
↓
Actions
↓
Python Tests
↓
Workflow Run
↓
Artifacts
Download the desired HTML coverage artifact, extract it, and open:
index.html
to inspect the complete coverage report locally.
The repository is structured approximately as:
vibe-coding/
│
├── generator.py
├── requirements-dev.txt
├── pytest.ini
├── README.md
├── .gitignore
│
├── tests/
│ └── test_generator.py
│
├── scripts/
│ ├── test.sh
│ ├── test_all.sh
│ ├── test_compile.sh
│ ├── test_coverage.sh
│ ├── test_coverage_enforce.sh
│ ├── test_coverage_html.sh
│ ├── test_fast.sh
│ ├── test_single.sh
│ └── test_verbose.sh
│
└── .github/
└── workflows/
└── test.yml
Generated projects are written separately under the configured output directory.
Clone the repository:
git clone <repository-url>
cd vibe-codingCreate a virtual environment:
python3 -m venv .venvActivate it on macOS/Linux:
source .venv/bin/activateUpgrade pip:
python -m pip install --upgrade pipInstall development dependencies:
pip install -r requirements-dev.txtRun the generator:
python generator.pyRun the tests:
./scripts/test.shRun the complete local verification:
./scripts/test_all.shA typical development cycle for this repository is:
Create / modify functionality
↓
Run generator
↓
Inspect generated output
↓
Run pytest
↓
Run coverage
↓
Run full local checks
↓
Commit changes
↓
Push development branch
↓
Open pull request
↓
GitHub Actions executes
↓
Tests + 100% coverage required
↓
Inspect downloadable coverage reports
↓
Merge
This creates multiple layers of verification between AI-generated implementation and production code.
The purpose of this repository is not simply to generate random Python files.
It is an experiment in combining AI-assisted development with traditional software engineering verification.
The basic philosophy is:
Vibe Code
↓
Execute
↓
Observe
↓
Test
↓
Measure
↓
Automate
↓
Verify
↓
Iterate
AI can dramatically accelerate implementation, but implementation speed does not remove the need for verification.
This project explores how quickly functional software can be developed with AI while still introducing automated testing, reproducibility, regression protection, coverage measurement, and continuous integration around that software.
In other words:
Vibe code the implementation, then engineer confidence into the result.