Metadata-Version: 2.4
Name: pytest-casewise-package-install
Version: 0.2.0
Summary: A pytest plugin for test case-level dynamic dependency management
Home-page: https://github.com/yourusername/pytest-casewise-package-install
Author: pytest-casewise-package-install Contributors
License: MIT
Project-URL: Homepage, https://github.com/yourusername/pytest-casewise-package-install
Project-URL: Repository, https://github.com/yourusername/pytest-casewise-package-install
Project-URL: Issues, https://github.com/yourusername/pytest-casewise-package-install/issues
Keywords: pytest,plugin,package,dependency,isolation,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Pytest
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pytest>=6.0.0
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# pytest-casewise-package-install

[English](#english) | [??](#??)

---

## English

A pytest plugin for test case-level dynamic dependency management. Solves dependency conflicts between multiple test cases by automatically installing required package versions before test execution and cleaning up the environment afterward, ensuring isolation and consistency.

### Features

- ?? **Test Case-Level Package Management**: Specify different package versions for each test case
- ?? **Dependency Isolation**: Avoid conflicts between tests requiring different package versions
- ?? **Automatic Installation**: Packages are installed automatically before test execution
- ?? **Automatic Cleanup**: Environment is restored after each test
- ?? **Smart Caching**: Package installations are cached and reused across tests
- ?? **Multiple Usage Patterns**: Decorator or marker-based syntax

### Installation

```bash
pip install pytest-casewise-package-install
```

### Quick Start

#### Using Decorator

```python
from pytest_casewise_package_install import with_packages

@with_packages({"requests": "2.31.0"})
def test_with_requests():
    import requests
    assert requests.__version__ == "2.31.0"
```

#### Using Pytest Marker

```python
import pytest

@pytest.mark.with_packages(packages={"requests": "2.28.0"})
def test_with_marker():
    import requests
    assert requests.__version__ == "2.28.0"
```

#### Multiple Packages

```python
from pytest_casewise_package_install import with_packages

@with_packages({
    "numpy": "1.26.4",
    "pandas": "2.0.0"
})
def test_multiple_packages():
    import numpy
    import pandas
    assert numpy.__version__ == "1.26.4"
    assert pandas.__version__ == "2.0.0"
```

#### Parametrize with Different Versions (NEW!)

Test the same code with different package versions - perfect for model testing:

```python
import pytest
from pytest_casewise_package_install import param_with_packages

@pytest.mark.parametrize("model_name,packages", [
    param_with_packages(
        "bert-base-uncased",
        packages={"transformers": "4.30.0"},
        id="bert-v4.30"
    ),
    param_with_packages(
        "gpt2",
        packages={"transformers": "4.35.0"},
        id="gpt2-v4.35"
    ),
])
def test_model(model_name, packages):
    import transformers
    print(f"Testing {model_name} with transformers {transformers.__version__}")
    # your test code
```

#### Using Fixtures for Dynamic Management

```python
from pytest_casewise_package_install import package_env

def test_with_fixture(package_env):
    with package_env.use_packages({"numpy": "1.24.0"}):
        import numpy
        assert numpy.__version__ == "1.24.0"
    # environment automatically restored
```

### Configuration

You can configure the plugin behavior in `pytest.ini` or `setup.cfg`:

```ini
[pytest]
# custom cache directory (optional)
casewise_cache_dir = ~/.my_custom_cache

# automatically cleanup environment after each test (default: true)
casewise_auto_cleanup = true

# package installation timeout in seconds (default: 300)
casewise_install_timeout = 300

# verbose output (default: false)
casewise_verbose = true
```

Or use environment variables:

```bash
export CASEWISE_CACHE_DIR=~/.my_custom_cache
export CASEWISE_AUTO_CLEANUP=true
export CASEWISE_INSTALL_TIMEOUT=300
export CASEWISE_VERBOSE=true
```

### How It Works

1. **Test Discovery**: The plugin hooks into pytest's test collection phase
2. **Package Detection**: Detects package requirements from decorators or markers
3. **Environment Setup**: Before test execution:
   - Creates isolated installation directory for required packages
   - Installs packages using `pip install --target`
   - Modifies `PYTHONPATH` and `sys.path` to use the isolated packages
4. **Test Execution**: Test runs with the specified package versions
5. **Cleanup**: After test execution:
   - Restores original `PYTHONPATH` and `sys.path`
   - Keeps installed packages cached for future tests

### Advanced Usage

#### Test Class with Different Versions

```python
from pytest_casewise_package_install import with_packages

class TestPackageVersions:
    @with_packages({"click": "8.1.3"})
    def test_click_8_1_3(self):
        import click
        assert click.__version__ == "8.1.3"
    
    @with_packages({"click": "8.0.0"})
    def test_click_8_0_0(self):
        import click
        assert click.__version__ == "8.0.0"
```

#### Reusing Package Sets

The plugin automatically caches package installations. If two tests require the same package set, the second test will reuse the first test's installation:

```python
from pytest_casewise_package_install import with_packages

@with_packages({"requests": "2.31.0"})
def test_one():
    import requests
    assert requests.__version__ == "2.31.0"

@with_packages({"requests": "2.31.0"})
def test_two():
    # reuses the installation from test_one
    import requests
    assert requests.__version__ == "2.31.0"
```

### Use Cases

This plugin is particularly useful when:

- Testing compatibility with multiple versions of a dependency
- Running tests that require conflicting package versions
- Testing migration paths between package versions
- Ensuring test isolation in CI/CD pipelines
- Testing against different versions of transitive dependencies

### Limitations

- Package installation happens during test setup, which may increase test duration
- Large packages can consume significant disk space in the cache directory
- Some packages with complex native dependencies may not work correctly with `--target` installation
- Import-time side effects in packages may not be fully isolated

### Development

#### Setup Development Environment

```bash
git clone https://github.com/yourusername/pytest-casewise-package-install
cd pytest-casewise-package-install
pip install -e .
```

#### Run Tests

```bash
pytest tests/
```

#### Run Examples

```bash
cd examples
pytest -v
```

### License

MIT License

---

## ??

????????????????? pytest ?????????????????????????????????????????????????????????

### ????

- ?? **????????**: ???????????????
- ?? **????**: ??????????????????
- ?? **????**: ???????????
- ?? **????**: ?????????
- ?? **????**: ?????????????
- ?? **??????**: ???????????

### ??

```bash
pip install pytest-casewise-package-install
```

### ????

#### ?????

```python
from pytest_casewise_package_install import with_packages

@with_packages({"requests": "2.31.0"})
def test_with_requests():
    import requests
    assert requests.__version__ == "2.31.0"
```

#### ?? Pytest Marker

```python
import pytest

@pytest.mark.with_packages(packages={"requests": "2.28.0"})
def test_with_marker():
    import requests
    assert requests.__version__ == "2.28.0"
```

#### ???

```python
from pytest_casewise_package_install import with_packages

@with_packages({
    "numpy": "1.26.4",
    "pandas": "2.0.0"
})
def test_multiple_packages():
    import numpy
    import pandas
    assert numpy.__version__ == "1.26.4"
    assert pandas.__version__ == "2.0.0"
```

### ??

??? `pytest.ini` ? `setup.cfg` ????????

```ini
[pytest]
# ???????????
casewise_cache_dir = ~/.my_custom_cache

# ??????????????: true?
casewise_auto_cleanup = true

# ????????????: 300?
casewise_install_timeout = 300

# ???????: false?
casewise_verbose = true
```

????????

```bash
export CASEWISE_CACHE_DIR=~/.my_custom_cache
export CASEWISE_AUTO_CLEANUP=true
export CASEWISE_INSTALL_TIMEOUT=300
export CASEWISE_VERBOSE=true
```

### ????

1. **????**: ???? pytest ???????
2. **???**: ?????????????
3. **????**: ???????
   - ??????????????
   - ?? `pip install --target` ???
   - ?? `PYTHONPATH` ? `sys.path` ???????
4. **????**: ????????????
5. **??**: ??????
   - ????? `PYTHONPATH` ? `sys.path`
   - ??????????????????

### ????

#### ??????????

```python
from pytest_casewise_package_install import with_packages

class TestPackageVersions:
    @with_packages({"click": "8.1.3"})
    def test_click_8_1_3(self):
        import click
        assert click.__version__ == "8.1.3"
    
    @with_packages({"click": "8.0.0"})
    def test_click_8_0_0(self):
        import click
        assert click.__version__ == "8.0.0"
```

#### ?????

???????????????????????????????????????????

```python
from pytest_casewise_package_install import with_packages

@with_packages({"requests": "2.31.0"})
def test_one():
    import requests
    assert requests.__version__ == "2.31.0"

@with_packages({"requests": "2.31.0"})
def test_two():
    # ???? test_one ???
    import requests
    assert requests.__version__ == "2.31.0"
```

### ????

??????????????

- ??????????????
- ????????????
- ????????????
- ? CI/CD ?????????
- ???????????

### ??

- ????????????????????????
- ????????????????????
- ???????????????????? `--target` ??
- ?????????????????

### ??

#### ??????

```bash
git clone https://github.com/yourusername/pytest-casewise-package-install
cd pytest-casewise-package-install
pip install -e .
```

#### ????

```bash
pytest tests/
```

#### ????

```bash
cd examples
pytest -v
```

### ???

MIT License
