Metadata-Version: 2.4
Name: eazytester
Version: 26.5.3
Summary: Utility for running unit tests and logging results in a structured format.
Author-email: Aric Kraft <kraft.aric@gmail.com>
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown

# EazyTests

A robust and easy-to-use test runner for Python unittest test classes with automatic logging and reporting.

## Overview

EazyTests provides a simple yet powerful `Engine` class that allows you to run one or more unittest test classes, capture results, and automatically log them to a file. Perfect for test automation, CI/CD pipelines, and test suite management.

## Features

- ✅ Run one or multiple test classes in a single call
- ✅ Automatic test result logging with timestamps
- ✅ Comprehensive test reporting (passed, failed, errors, skipped)
- ✅ Detailed failure and error tracebacks in log files
- ✅ Optional automatic log file opening
- ✅ Method chaining for fluent API
- ✅ Programmatic access to test results

## Installation

```bash
pip install eazytests
```

## Quick Start

### Basic Usage

```python
from unittest import TestCase
from eazytester import Engine

class TestReaders(TestCase):
    def test_read_txt_file(self):
        # Your test code here
        self.assertTrue(True)

    def test_read_xlsx_file(self):
        # Your test code here
        self.assertIsNotNone({})

# Run tests
engine = Engine()
success = engine.add_tests(TestReaders).run_tests()

print(f"All tests passed: {success}")
```

### Multiple Test Classes

```python
from eazytester import Engine

engine = Engine(output_file="results/test_report.log")
success = engine.add_tests(TestReaders, TestWriters, TestParsers).run_tests()
```

### Without Auto-opening Log File

```python
engine = Engine(output_file="test_results.log", open_log=False)
engine.add_tests(TestReaders).run_tests()
```

### Accessing Results Programmatically

```python
engine = Engine()
engine.add_tests(TestReaders).run_tests()

results = engine.get_results()
print(f"Total tests: {results['total_tests']}")
print(f"Failures: {results['failures']}")
print(f"Errors: {results['errors']}")
print(f"Success: {results['success']}")
```

## API Reference

### Engine Class

#### Constructor

```python
Engine(output_file: Optional[str] = None, open_log: bool = True)
```

**Parameters:**

- `output_file` (str, optional): Path to the log file. Defaults to `'test_results.log'`
- `open_log` (bool, optional): Whether to automatically open the log file after writing. Defaults to `True`

#### Methods

##### `add_tests(*test_classes: Type[TestCase]) -> Engine`

Add one or more test classes to run.

**Parameters:**

- `*test_classes`: One or more `unittest.TestCase` subclasses

**Returns:** Engine instance (allows method chaining)

**Raises:** `ValueError` if a class is not a subclass of `unittest.TestCase`

**Example:**

```python
engine.add_tests(TestClass1, TestClass2, TestClass3)
```

##### `run_tests() -> bool`

Execute all added test classes and log results.

**Returns:** `True` if all tests passed, `False` otherwise

**Raises:** `RuntimeError` if no test classes have been added

**Example:**

```python
success = engine.run_tests()
```

##### `get_results() -> dict`

Get test results summary.

**Returns:** Dictionary containing:

- `total_tests` (int): Total number of tests run
- `failures` (int): Number of test failures
- `errors` (int): Number of test errors
- `skipped` (int): Number of skipped tests
- `success` (bool): Whether all tests passed
- `output` (str): Detailed test output
- `failures_detail` (list): List of (test, traceback) tuples for failures
- `errors_detail` (list): List of (test, traceback) tuples for errors

**Example:**

```python
results = engine.get_results()
```

## Log File Format

The generated log file includes:

```
Test Results - 2026-05-15 10:30:45
============================================================

SUMMARY
------------------------------------------------------------
Total Tests: 5
Passed: 4
Failures: 0
Errors: 1
Skipped: 0
Status: ✗ FAILED

DETAILED OUTPUT
------------------------------------------------------------
[Detailed test runner output...]

ERRORS
------------------------------------------------------------
[Error tracebacks if any...]
```

## Examples

### Example 1: Running Tests from a Single Class

```python
from unittest import TestCase
from eazytester import Engine

class TestMathOperations(TestCase):
    def test_addition(self):
        self.assertEqual(2 + 2, 4)

    def test_subtraction(self):
        self.assertEqual(5 - 2, 3)

engine = Engine(output_file="math_tests.log")
success = engine.add_tests(TestMathOperations).run_tests()
```

### Example 2: Running Multiple Test Suites

```python
from eazytester import Engine

engine = Engine(output_file="full_test_suite.log")
engine.add_tests(
    TestDataParsers,
    TestFileReaders,
    TestDataValidators
).run_tests()
```

### Example 3: Suppressing Auto-Open and Manual Result Checking

```python
engine = Engine(output_file="results.log", open_log=False)
engine.add_tests(MyTestClass).run_tests()

results = engine.get_results()
if not results['success']:
    print(f"Tests failed! {results['failures']} failures, {results['errors']} errors")
```

## Requirements

- Python 3.7+
- unittest (built-in standard library)

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

## Support

For issues, questions, or suggestions, please open an issue on the project repository.
