Metadata-Version: 2.4
Name: AIUnitTest
Version: 0.0.7
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: 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.

## 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.
