Metadata-Version: 2.4
Name: AIUnitTest
Version: 0.0.8
Summary: CLI to generate and update Python unit tests automatically using coverage and AI
Author: Ofido
Project-URL: Homepage, https://github.com/ofido/AIUnitTest
Project-URL: Bug Tracker, https://github.com/ofido/AIUnitTest/issues
Keywords: testing,coverage,openai,automation
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai==2.3.0
Requires-Dist: coverage==7.10.7
Requires-Dist: typer==0.19.2
Requires-Dist: tomli==2.3.0
Requires-Dist: typing-extensions==4.15.0
Provides-Extra: huggingface
Requires-Dist: sentence-transformers==5.1.1; extra == "huggingface"
Requires-Dist: huggingface-hub==0.35.3; extra == "huggingface"
Provides-Extra: faiss
Requires-Dist: faiss-cpu==1.12.0; extra == "faiss"
Requires-Dist: numpy==2.3.3; extra == "faiss"
Requires-Dist: scikit-learn==1.7.2; extra == "faiss"
Requires-Dist: joblib==1.5.2; extra == "faiss"
Provides-Extra: all
Requires-Dist: sentence-transformers==5.1.1; extra == "all"
Requires-Dist: huggingface-hub==0.35.3; extra == "all"
Requires-Dist: faiss-cpu==1.12.0; extra == "all"
Requires-Dist: numpy==2.3.3; extra == "all"
Requires-Dist: scikit-learn==1.7.2; extra == "all"
Requires-Dist: joblib==1.5.2; extra == "all"
Requires-Dist: psutil==7.1.0; extra == "all"
Provides-Extra: dev
Requires-Dist: black==25.9.0; extra == "dev"
Requires-Dist: isort==7.0.0; extra == "dev"
Requires-Dist: flake8==7.3.0; extra == "dev"
Requires-Dist: flake8-bugbear==24.12.12; extra == "dev"
Requires-Dist: flake8-annotations==3.2.0; extra == "dev"
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev"
Requires-Dist: flake8-comprehensions==3.17.0; extra == "dev"
Requires-Dist: flake8-eradicate==1.5.0; extra == "dev"
Requires-Dist: flake8-pytest-style==2.1.0; extra == "dev"
Requires-Dist: mypy==1.18.2; extra == "dev"
Requires-Dist: pre-commit==4.3.0; extra == "dev"
Requires-Dist: pytest==8.4.2; extra == "dev"
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio==1.2.0; extra == "dev"
Requires-Dist: pytest-dotenv==0.5.2; extra == "dev"
Requires-Dist: joblib-stubs==1.5.2.0.20250831; extra == "dev"
Requires-Dist: types-psutil==7.0.0.20251001; extra == "dev"
Requires-Dist: pytest-mock==3.15.1; extra == "dev"
Requires-Dist: psutil==7.1.0; extra == "dev"
Dynamic: license-file

# AIUnitTest

[![PyPI version](https://badge.fury.io/py/AIUnitTest.svg)](https://badge.fury.io/py/AIUnitTest)
[![Python versions](https://img.shields.io/pypi/pyversions/AIUnitTest.svg)](https://pypi.org/project/AIUnitTest)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Linter: flake8](https://img.shields.io/badge/linter-flake8-blue.svg)](https://flake8.pycqa.org/en/latest/)
[![Static typing: mypy](https://img.shields.io/badge/static%20typing-mypy-blue.svg)](https://mypy-lang.org/)
[![Testing: pytest](https://img.shields.io/badge/testing-pytest-blue.svg)](https://pytest.org)
[![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](https://coverage.readthedocs.io/)
[![CI/CD](https://github.com/ofido/AIUnitTest/actions/workflows/ci.yml/badge.svg)](https://github.com/ofido/AIUnitTest/actions/workflows/ci.yml)
[![GitHub last commit](https://img.shields.io/github/last-commit/ofido/AIUnitTest)](https://github.com/ofido/AIUnitTest/commits/main)
[![GitHub repo size](https://img.shields.io/github/repo-size/ofido/AIUnitTest)](https://github.com/ofido/AIUnitTest)
[![GitHub issues](https://img.shields.io/github/issues/ofido/AIUnitTest)](https://github.com/ofido/AIUnitTest/issues)

AIUnitTest is a command-line tool that reads your `pyproject.toml` and test coverage
data (`.coverage`) to generate and update missing Python unit tests using AI.

## Status

The current public CLI and README still describe the v1 workflow.

AIUnitTest v2 is now being defined as a redesign around a tool-first test execution layer for coding agents.
It will ship first through its own CLI client and later expose the same core to external agents.
The product direction is to become the specialized testing layer that works with coding agents,
instead of competing with them as a general-purpose agent.
The v2 planning and architecture docs live in:

- `docs/v2/README.md`
- `docs/v2/architecture.md`
- `docs/v2/implementation-plan.md`

## How it Works

1. **Coverage Analysis**: The tool uses `coverage.py` to identify lines of code
    that are not covered by your existing test suite.
2. **Source Code Chunking**: It breaks down the source code into logical chunks
    (functions and classes).
3. **AI-Powered Test Generation**: For each chunk with uncovered lines,
    it sends the source code and the uncovered line numbers to an AI model
    (like OpenAI's GPT) to generate new test cases.
4. **Test File Updates**: The newly generated tests are appended to the
    corresponding test file.

## Features

- **Coverage Analysis**: Uses the Coverage.py API to identify untested lines.
- **AI-Powered Test Generation**: Calls OpenAI GPT to create or enhance test cases.
- **Config-Driven**: Automatically picks up `coverage.run.source` and
  `pytest.ini_options.testpaths` from `pyproject.toml`.
- **Auto Mode**: The `--auto` flag sets source and tests directories without
  manual arguments.
- **Async & Parallel**: Speeds up OpenAI requests for large codebases.

## Installation

There are two ways to install AIUnitTest:

### From PyPI

You can install the latest stable version from PyPI:

```bash
pip install AIUnitTest
```

### Optional Dependencies

AIUnitTest supports optional features that can be installed as needed:

#### Basic Installation (OpenAI only)

```bash
pip install AIUnitTest
```

#### With HuggingFace Support

```bash
pip install AIUnitTest[huggingface]
```

#### With FAISS Indexing Support

```bash
pip install AIUnitTest[faiss]
```

#### All Optional Features

```bash
pip install AIUnitTest[all]
```

#### Development Dependencies

```bash
pip install AIUnitTest[dev]
```

You can also combine multiple extras:

```bash
pip install AIUnitTest[huggingface,faiss]
```

### From GitHub (for the latest development version)

1. **Clone the repository:**

    ```bash
    git clone https://github.com/ofido/AIUnitTest.git
    cd AIUnitTest
    ```

2. **Install the project in editable mode:**

    ```bash
    pip install -e .
    # Or with optional dependencies:
    pip install -e .[all]
    ```

## Usage

### Automatic Mode

The easiest way to run the tool is in automatic mode.
It will automatically discover your source and test folders
from your `pyproject.toml` file.

```bash
ai-unit-test --auto
```

### Manual Mode

You can also specify the source and test folders manually:

```bash
ai-unit-test --folders src --tests-folder tests
```

### Generating a Test for a Specific Function

You can also generate a test for a single function:

```bash
ai-unit-test func my_module/my_file.py my_function
```

### Indexing and Searching Tests

You can index your tests for semantic search:

```bash
ai-unit-test index
```

And then search for tests related to a specific query:

```bash
ai-unit-test search "my search query"
```

### Command-Line Options

- `--folders`: The source code folders to analyze.
- `--tests-folder`: The folder where the tests are located.
- `--coverage-file`: The path to the `.coverage` file.
- `--auto`: Try to discover folders/tests from `pyproject.toml`.

## Configuration

AIUnitTest uses the standard `pyproject.toml` file for configuration.
Here are the relevant sections:

- **`[tool.coverage.run]`**:
  - `source`: A list of source code folders.
- **`[tool.pytest.ini_options]`**:
  - `testpaths`: A list of test folders.

## Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue.

## License

This project is licensed under the MIT License
see the [LICENSE](LICENSE) file for details.
