pytest-llm-assert 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytest_llm_assert-0.2.0/.github/CODEOWNERS +8 -0
- pytest_llm_assert-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- pytest_llm_assert-0.2.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
- pytest_llm_assert-0.2.0/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- pytest_llm_assert-0.2.0/.github/PULL_REQUEST_TEMPLATE.md +25 -0
- pytest_llm_assert-0.2.0/.github/dependabot.yml +27 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/.github/workflows/ci.yml +13 -13
- pytest_llm_assert-0.2.0/.github/workflows/codeql.yml +42 -0
- pytest_llm_assert-0.2.0/.github/workflows/dependency-review.yml +23 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/.github/workflows/release.yml +8 -8
- pytest_llm_assert-0.2.0/.github/workflows/stale.yml +35 -0
- pytest_llm_assert-0.2.0/.pre-commit-config.yaml +16 -0
- pytest_llm_assert-0.2.0/CODE_OF_CONDUCT.md +30 -0
- pytest_llm_assert-0.2.0/CONTRIBUTING.md +116 -0
- pytest_llm_assert-0.2.0/PKG-INFO +135 -0
- pytest_llm_assert-0.2.0/README.md +103 -0
- pytest_llm_assert-0.2.0/SECURITY.md +27 -0
- pytest_llm_assert-0.2.0/docs/GITHUB_SETUP_GUIDE.md +833 -0
- pytest_llm_assert-0.2.0/docs/README.md +15 -0
- pytest_llm_assert-0.2.0/docs/api-reference.md +150 -0
- pytest_llm_assert-0.2.0/docs/comparing-models.md +25 -0
- pytest_llm_assert-0.2.0/docs/configuration.md +38 -0
- pytest_llm_assert-0.2.0/examples/conftest.py +21 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/pyproject.toml +10 -8
- pytest_llm_assert-0.2.0/src/pytest_llm_assert/__init__.py +6 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/src/pytest_llm_assert/core.py +67 -14
- pytest_llm_assert-0.2.0/src/pytest_llm_assert/prompts/system_prompt.md +4 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/tests/integration/test_llm_integration.py +8 -6
- pytest_llm_assert-0.2.0/tests/unit/test_assertion_result.py +53 -0
- pytest_llm_assert-0.2.0/tests/unit/test_azure_auth.py +163 -0
- pytest_llm_assert-0.2.0/tests/unit/test_error_handling.py +66 -0
- pytest_llm_assert-0.2.0/tests/unit/test_fixture_integration.py +12 -0
- pytest_llm_assert-0.2.0/tests/unit/test_llm_assert_core.py +199 -0
- pytest_llm_assert-0.2.0/tests/unit/test_llm_response.py +35 -0
- pytest_llm_assert-0.2.0/tests/unit/test_plugin.py +93 -0
- pytest_llm_assert-0.2.0/tests/unit/test_response_parsing.py +187 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/uv.lock +241 -11
- pytest_llm_assert-0.1.0/PKG-INFO +0 -246
- pytest_llm_assert-0.1.0/README.md +0 -216
- pytest_llm_assert-0.1.0/src/pytest_llm_assert/__init__.py +0 -6
- pytest_llm_assert-0.1.0/tests/unit/test_llm_assert.py +0 -214
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/.env.example +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/.gitignore +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/LICENSE +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/examples/README.md +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/examples/pytest_conftest.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/examples/test_basic.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/examples/test_compare_models.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/src/pytest_llm_assert/plugin.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/tests/__init__.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/tests/integration/__init__.py +0 -0
- {pytest_llm_assert-0.1.0 → pytest_llm_assert-0.2.0}/tests/unit/__init__.py +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Report a bug to help us improve
|
|
4
|
+
title: '[BUG] '
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Bug Description
|
|
10
|
+
A clear description of what the bug is.
|
|
11
|
+
|
|
12
|
+
## To Reproduce
|
|
13
|
+
Steps to reproduce:
|
|
14
|
+
1. ...
|
|
15
|
+
2. ...
|
|
16
|
+
|
|
17
|
+
## Expected Behavior
|
|
18
|
+
What you expected to happen.
|
|
19
|
+
|
|
20
|
+
## Actual Behavior
|
|
21
|
+
What actually happened.
|
|
22
|
+
|
|
23
|
+
## Environment
|
|
24
|
+
- pytest-llm-assert version:
|
|
25
|
+
- Python version:
|
|
26
|
+
- OS:
|
|
27
|
+
- LLM provider/model:
|
|
28
|
+
|
|
29
|
+
## Code Example
|
|
30
|
+
```python
|
|
31
|
+
# Minimal code to reproduce the issue
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Error Output
|
|
35
|
+
```
|
|
36
|
+
# Paste any error messages or tracebacks
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Additional Context
|
|
40
|
+
Any other context about the problem.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Documentation
|
|
4
|
+
url: https://github.com/sbroenne/pytest-llm-assert#readme
|
|
5
|
+
about: Check the documentation before opening an issue
|
|
6
|
+
- name: Discussions
|
|
7
|
+
url: https://github.com/sbroenne/pytest-llm-assert/discussions
|
|
8
|
+
about: Ask questions and discuss ideas
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
title: '[FEATURE] '
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Problem
|
|
10
|
+
Describe the problem or limitation you're facing.
|
|
11
|
+
|
|
12
|
+
## Proposed Solution
|
|
13
|
+
Describe what you'd like to happen.
|
|
14
|
+
|
|
15
|
+
## Alternatives Considered
|
|
16
|
+
Describe any alternative solutions you've considered.
|
|
17
|
+
|
|
18
|
+
## Use Case
|
|
19
|
+
Explain how this feature would benefit users.
|
|
20
|
+
|
|
21
|
+
## Additional Context
|
|
22
|
+
Any other context, examples, or screenshots.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
|
|
3
|
+
Brief description of the changes.
|
|
4
|
+
|
|
5
|
+
## Type of Change
|
|
6
|
+
|
|
7
|
+
- [ ] Bug fix (non-breaking change that fixes an issue)
|
|
8
|
+
- [ ] New feature (non-breaking change that adds functionality)
|
|
9
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
10
|
+
- [ ] Documentation update
|
|
11
|
+
|
|
12
|
+
## Checklist
|
|
13
|
+
|
|
14
|
+
- [ ] I have run `pre-commit run --all-files` and all checks pass
|
|
15
|
+
- [ ] I have added tests that prove my fix/feature works
|
|
16
|
+
- [ ] I have updated the documentation if needed
|
|
17
|
+
- [ ] My changes generate no new warnings
|
|
18
|
+
|
|
19
|
+
## Testing
|
|
20
|
+
|
|
21
|
+
Describe the tests you added or ran.
|
|
22
|
+
|
|
23
|
+
## Related Issues
|
|
24
|
+
|
|
25
|
+
Fixes #(issue number)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python dependencies
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "monday"
|
|
9
|
+
open-pull-requests-limit: 5
|
|
10
|
+
labels:
|
|
11
|
+
- "dependencies"
|
|
12
|
+
- "python"
|
|
13
|
+
commit-message:
|
|
14
|
+
prefix: "chore(deps)"
|
|
15
|
+
|
|
16
|
+
# GitHub Actions
|
|
17
|
+
- package-ecosystem: "github-actions"
|
|
18
|
+
directory: "/"
|
|
19
|
+
schedule:
|
|
20
|
+
interval: "weekly"
|
|
21
|
+
day: "monday"
|
|
22
|
+
open-pull-requests-limit: 5
|
|
23
|
+
labels:
|
|
24
|
+
- "dependencies"
|
|
25
|
+
- "github-actions"
|
|
26
|
+
commit-message:
|
|
27
|
+
prefix: "chore(deps)"
|
|
@@ -2,7 +2,7 @@ name: CI
|
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
5
|
-
branches: [main]
|
|
5
|
+
branches: [main, 'feature/**', 'fix/**', 'dev/**']
|
|
6
6
|
pull_request:
|
|
7
7
|
branches: [main]
|
|
8
8
|
workflow_dispatch:
|
|
@@ -12,15 +12,15 @@ jobs:
|
|
|
12
12
|
name: Lint
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
|
-
- uses: actions/checkout@
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
16
|
|
|
17
17
|
- name: Install uv
|
|
18
|
-
uses: astral-sh/setup-uv@
|
|
18
|
+
uses: astral-sh/setup-uv@v7
|
|
19
19
|
with:
|
|
20
20
|
version: "latest"
|
|
21
21
|
|
|
22
22
|
- name: Set up Python
|
|
23
|
-
uses: actions/setup-python@
|
|
23
|
+
uses: actions/setup-python@v6
|
|
24
24
|
with:
|
|
25
25
|
python-version: "3.13"
|
|
26
26
|
|
|
@@ -37,15 +37,15 @@ jobs:
|
|
|
37
37
|
name: Type Check
|
|
38
38
|
runs-on: ubuntu-latest
|
|
39
39
|
steps:
|
|
40
|
-
- uses: actions/checkout@
|
|
40
|
+
- uses: actions/checkout@v6
|
|
41
41
|
|
|
42
42
|
- name: Install uv
|
|
43
|
-
uses: astral-sh/setup-uv@
|
|
43
|
+
uses: astral-sh/setup-uv@v7
|
|
44
44
|
with:
|
|
45
45
|
version: "latest"
|
|
46
46
|
|
|
47
47
|
- name: Set up Python
|
|
48
|
-
uses: actions/setup-python@
|
|
48
|
+
uses: actions/setup-python@v6
|
|
49
49
|
with:
|
|
50
50
|
python-version: "3.13"
|
|
51
51
|
|
|
@@ -63,15 +63,15 @@ jobs:
|
|
|
63
63
|
matrix:
|
|
64
64
|
python-version: ["3.11", "3.12", "3.13"]
|
|
65
65
|
steps:
|
|
66
|
-
- uses: actions/checkout@
|
|
66
|
+
- uses: actions/checkout@v6
|
|
67
67
|
|
|
68
68
|
- name: Install uv
|
|
69
|
-
uses: astral-sh/setup-uv@
|
|
69
|
+
uses: astral-sh/setup-uv@v7
|
|
70
70
|
with:
|
|
71
71
|
version: "latest"
|
|
72
72
|
|
|
73
73
|
- name: Set up Python ${{ matrix.python-version }}
|
|
74
|
-
uses: actions/setup-python@
|
|
74
|
+
uses: actions/setup-python@v6
|
|
75
75
|
with:
|
|
76
76
|
python-version: ${{ matrix.python-version }}
|
|
77
77
|
|
|
@@ -85,15 +85,15 @@ jobs:
|
|
|
85
85
|
name: Smoke Test
|
|
86
86
|
runs-on: ubuntu-latest
|
|
87
87
|
steps:
|
|
88
|
-
- uses: actions/checkout@
|
|
88
|
+
- uses: actions/checkout@v6
|
|
89
89
|
|
|
90
90
|
- name: Install uv
|
|
91
|
-
uses: astral-sh/setup-uv@
|
|
91
|
+
uses: astral-sh/setup-uv@v7
|
|
92
92
|
with:
|
|
93
93
|
version: "latest"
|
|
94
94
|
|
|
95
95
|
- name: Set up Python
|
|
96
|
-
uses: actions/setup-python@
|
|
96
|
+
uses: actions/setup-python@v6
|
|
97
97
|
with:
|
|
98
98
|
python-version: "3.13"
|
|
99
99
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
# Run weekly on Sundays at 00:00 UTC
|
|
10
|
+
- cron: "0 0 * * 0"
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
analyze:
|
|
14
|
+
name: Analyze
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
actions: read
|
|
18
|
+
contents: read
|
|
19
|
+
security-events: write
|
|
20
|
+
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
language: [python]
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout repository
|
|
28
|
+
uses: actions/checkout@v6
|
|
29
|
+
|
|
30
|
+
- name: Initialize CodeQL
|
|
31
|
+
uses: github/codeql-action/init@v4
|
|
32
|
+
with:
|
|
33
|
+
languages: ${{ matrix.language }}
|
|
34
|
+
queries: security-extended,security-and-quality
|
|
35
|
+
|
|
36
|
+
- name: Autobuild
|
|
37
|
+
uses: github/codeql-action/autobuild@v4
|
|
38
|
+
|
|
39
|
+
- name: Perform CodeQL Analysis
|
|
40
|
+
uses: github/codeql-action/analyze@v4
|
|
41
|
+
with:
|
|
42
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Dependency Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
dependency-review:
|
|
13
|
+
name: Dependency Review
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v6
|
|
18
|
+
|
|
19
|
+
- name: Dependency Review
|
|
20
|
+
uses: actions/dependency-review-action@v4
|
|
21
|
+
with:
|
|
22
|
+
fail-on-severity: high
|
|
23
|
+
comment-summary-in-pr: always
|
|
@@ -10,15 +10,15 @@ jobs:
|
|
|
10
10
|
name: Build Package
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
12
|
steps:
|
|
13
|
-
- uses: actions/checkout@
|
|
13
|
+
- uses: actions/checkout@v6
|
|
14
14
|
|
|
15
15
|
- name: Install uv
|
|
16
|
-
uses: astral-sh/setup-uv@
|
|
16
|
+
uses: astral-sh/setup-uv@v7
|
|
17
17
|
with:
|
|
18
18
|
version: "latest"
|
|
19
19
|
|
|
20
20
|
- name: Set up Python
|
|
21
|
-
uses: actions/setup-python@
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
22
|
with:
|
|
23
23
|
python-version: "3.13"
|
|
24
24
|
|
|
@@ -50,13 +50,13 @@ jobs:
|
|
|
50
50
|
needs: build
|
|
51
51
|
steps:
|
|
52
52
|
- name: Download build artifacts
|
|
53
|
-
uses: actions/download-artifact@
|
|
53
|
+
uses: actions/download-artifact@v7
|
|
54
54
|
with:
|
|
55
55
|
name: dist
|
|
56
56
|
path: dist/
|
|
57
57
|
|
|
58
58
|
- name: Set up Python
|
|
59
|
-
uses: actions/setup-python@
|
|
59
|
+
uses: actions/setup-python@v6
|
|
60
60
|
with:
|
|
61
61
|
python-version: "3.13"
|
|
62
62
|
|
|
@@ -78,7 +78,7 @@ jobs:
|
|
|
78
78
|
id-token: write
|
|
79
79
|
steps:
|
|
80
80
|
- name: Download build artifacts
|
|
81
|
-
uses: actions/download-artifact@
|
|
81
|
+
uses: actions/download-artifact@v7
|
|
82
82
|
with:
|
|
83
83
|
name: dist
|
|
84
84
|
path: dist/
|
|
@@ -93,10 +93,10 @@ jobs:
|
|
|
93
93
|
permissions:
|
|
94
94
|
contents: write
|
|
95
95
|
steps:
|
|
96
|
-
- uses: actions/checkout@
|
|
96
|
+
- uses: actions/checkout@v6
|
|
97
97
|
|
|
98
98
|
- name: Download build artifacts
|
|
99
|
-
uses: actions/download-artifact@
|
|
99
|
+
uses: actions/download-artifact@v7
|
|
100
100
|
with:
|
|
101
101
|
name: dist
|
|
102
102
|
path: dist/
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Stale Issues and PRs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 0 * * *" # Run daily at midnight UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
issues: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
stale:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/stale@v10
|
|
17
|
+
with:
|
|
18
|
+
stale-issue-message: >
|
|
19
|
+
This issue has been automatically marked as stale because it has not had
|
|
20
|
+
recent activity. It will be closed if no further activity occurs within 7 days.
|
|
21
|
+
Thank you for your contributions!
|
|
22
|
+
stale-pr-message: >
|
|
23
|
+
This pull request has been automatically marked as stale because it has not had
|
|
24
|
+
recent activity. It will be closed if no further activity occurs within 7 days.
|
|
25
|
+
close-issue-message: >
|
|
26
|
+
This issue was closed because it has been stale for 7 days with no activity.
|
|
27
|
+
Feel free to reopen if this is still relevant.
|
|
28
|
+
close-pr-message: >
|
|
29
|
+
This pull request was closed because it has been stale for 7 days with no activity.
|
|
30
|
+
days-before-stale: 30
|
|
31
|
+
days-before-close: 7
|
|
32
|
+
stale-issue-label: "stale"
|
|
33
|
+
stale-pr-label: "stale"
|
|
34
|
+
exempt-issue-labels: "pinned,security,bug"
|
|
35
|
+
exempt-pr-labels: "pinned,security"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.14.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: local
|
|
10
|
+
hooks:
|
|
11
|
+
- id: pyright
|
|
12
|
+
name: pyright
|
|
13
|
+
entry: pyright
|
|
14
|
+
language: system
|
|
15
|
+
types: [python]
|
|
16
|
+
pass_filenames: false
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
Examples of behavior that contributes to a positive environment:
|
|
10
|
+
|
|
11
|
+
- Using welcoming and inclusive language
|
|
12
|
+
- Being respectful of differing viewpoints and experiences
|
|
13
|
+
- Gracefully accepting constructive criticism
|
|
14
|
+
- Focusing on what is best for the community
|
|
15
|
+
- Showing empathy towards other community members
|
|
16
|
+
|
|
17
|
+
Examples of unacceptable behavior:
|
|
18
|
+
|
|
19
|
+
- Trolling, insulting/derogatory comments, and personal or political attacks
|
|
20
|
+
- Public or private harassment
|
|
21
|
+
- Publishing others' private information without explicit permission
|
|
22
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
23
|
+
|
|
24
|
+
## Enforcement
|
|
25
|
+
|
|
26
|
+
Project maintainers are responsible for clarifying standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
|
27
|
+
|
|
28
|
+
## Attribution
|
|
29
|
+
|
|
30
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Contributing to pytest-llm-assert
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
1. Clone the repository:
|
|
6
|
+
```bash
|
|
7
|
+
git clone https://github.com/sbroenne/pytest-llm-assert.git
|
|
8
|
+
cd pytest-llm-assert
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
2. Create a virtual environment and install dependencies:
|
|
12
|
+
```bash
|
|
13
|
+
python -m venv .venv
|
|
14
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
15
|
+
pip install -e ".[dev]"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Install pre-commit hooks:
|
|
19
|
+
```bash
|
|
20
|
+
pre-commit install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Code Quality
|
|
24
|
+
|
|
25
|
+
This project uses automated tools to maintain code quality:
|
|
26
|
+
|
|
27
|
+
- **[Ruff](https://docs.astral.sh/ruff/)** — Linting and formatting
|
|
28
|
+
- **[Pyright](https://github.com/microsoft/pyright)** — Type checking
|
|
29
|
+
- **[pre-commit](https://pre-commit.com/)** — Git hooks for automated checks
|
|
30
|
+
|
|
31
|
+
### Running Checks Manually
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Run all pre-commit hooks
|
|
35
|
+
pre-commit run --all-files
|
|
36
|
+
|
|
37
|
+
# Or run individual tools
|
|
38
|
+
ruff check . # Linting
|
|
39
|
+
ruff format . # Formatting
|
|
40
|
+
pyright # Type checking
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Pre-commit Hooks
|
|
44
|
+
|
|
45
|
+
Pre-commit hooks run automatically on `git commit`. If a hook fails, fix the issues and commit again.
|
|
46
|
+
|
|
47
|
+
The hooks will:
|
|
48
|
+
1. **ruff** — Auto-fix linting issues where possible
|
|
49
|
+
2. **ruff-format** — Format code consistently
|
|
50
|
+
3. **pyright** — Check types
|
|
51
|
+
|
|
52
|
+
## Running Tests
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Run unit tests
|
|
56
|
+
pytest tests/unit/ -v
|
|
57
|
+
|
|
58
|
+
# Run all tests (requires LLM credentials)
|
|
59
|
+
pytest -v
|
|
60
|
+
|
|
61
|
+
# Run integration tests only
|
|
62
|
+
pytest -m integration -v
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Integration Tests
|
|
66
|
+
|
|
67
|
+
Integration tests require LLM provider credentials. Set up at least one:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Azure OpenAI (uses Entra ID - no API key needed)
|
|
71
|
+
export AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
|
|
72
|
+
az login
|
|
73
|
+
|
|
74
|
+
# Google Vertex AI
|
|
75
|
+
export GOOGLE_CLOUD_PROJECT=your-project-id
|
|
76
|
+
gcloud auth application-default login
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Project Structure
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
pytest-llm-assert/
|
|
83
|
+
├── src/pytest_llm_assert/
|
|
84
|
+
│ ├── __init__.py # Package exports
|
|
85
|
+
│ ├── core.py # LLMAssert implementation
|
|
86
|
+
│ └── plugin.py # pytest plugin (fixtures, CLI options)
|
|
87
|
+
├── tests/
|
|
88
|
+
│ ├── unit/ # Unit tests (mocked LLM calls)
|
|
89
|
+
│ └── integration/ # Integration tests (real LLM calls)
|
|
90
|
+
├── examples/ # Example usage patterns
|
|
91
|
+
├── pyproject.toml # Project configuration
|
|
92
|
+
└── .pre-commit-config.yaml
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Making Changes
|
|
96
|
+
|
|
97
|
+
1. Create a branch for your changes
|
|
98
|
+
2. Make your changes
|
|
99
|
+
3. Ensure all checks pass: `pre-commit run --all-files`
|
|
100
|
+
4. Run tests: `pytest tests/unit/ -v`
|
|
101
|
+
5. Submit a pull request
|
|
102
|
+
|
|
103
|
+
All PRs are **squash merged** to keep a clean commit history on main.
|
|
104
|
+
|
|
105
|
+
## Code Style
|
|
106
|
+
|
|
107
|
+
- Follow [PEP 8](https://peps.python.org/pep-0008/) (enforced by Ruff)
|
|
108
|
+
- Use type hints for all public APIs
|
|
109
|
+
- Keep functions focused and small
|
|
110
|
+
- Write docstrings for public classes and methods
|
|
111
|
+
|
|
112
|
+
## Releasing
|
|
113
|
+
|
|
114
|
+
1. Update version in `src/pytest_llm_assert/__init__.py` and `pyproject.toml`
|
|
115
|
+
2. Create a git tag: `git tag v0.x.x`
|
|
116
|
+
3. Push: `git push origin main --tags`
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-llm-assert
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Simple LLM-powered assertions for any pytest test
|
|
5
|
+
Project-URL: Homepage, https://github.com/sbroenne/pytest-llm-assert
|
|
6
|
+
Project-URL: Documentation, https://github.com/sbroenne/pytest-llm-assert#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/sbroenne/pytest-llm-assert
|
|
8
|
+
Author: Stefan Broenner
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,assertions,llm,pytest,testing
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Framework :: Pytest
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: azure-identity>=1.25
|
|
22
|
+
Requires-Dist: litellm>=1.81
|
|
23
|
+
Requires-Dist: pytest>=9.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pre-commit>=4.5; extra == 'dev'
|
|
26
|
+
Requires-Dist: pyright>=1.1.408; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=9.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: python-dotenv>=1.2; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.14; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# pytest-llm-assert
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/pytest-llm-assert/)
|
|
36
|
+
[](https://pypi.org/project/pytest-llm-assert/)
|
|
37
|
+
[](https://github.com/sbroenne/pytest-llm-assert/actions/workflows/ci.yml)
|
|
38
|
+
[](https://opensource.org/licenses/MIT)
|
|
39
|
+
|
|
40
|
+
**Natural language assertions for pytest.**
|
|
41
|
+
|
|
42
|
+
Testing a text-to-SQL agent? Validating LLM-generated code? Checking if error messages are helpful? Now you can:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
def test_sql_agent_output(llm):
|
|
46
|
+
sql = my_agent.generate("Get names of users over 21")
|
|
47
|
+
|
|
48
|
+
assert llm(sql, "Is this a valid SQL query that selects user names filtered by age > 21?")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The LLM evaluates your criterion and returns pass/fail — no regex, no parsing, no exact string matching.
|
|
52
|
+
|
|
53
|
+
## Features
|
|
54
|
+
|
|
55
|
+
- **Semantic assertions** — Assert meaning, not exact strings
|
|
56
|
+
- **100+ LLM providers** — OpenAI, Azure, Anthropic, Ollama, Vertex AI, Bedrock via [LiteLLM](https://docs.litellm.ai/)
|
|
57
|
+
- **pytest native** — Works as a standard pytest plugin/fixture
|
|
58
|
+
- **Response introspection** — Access tokens, cost, and reasoning via `llm.response`
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install pytest-llm-assert
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
# conftest.py
|
|
70
|
+
import pytest
|
|
71
|
+
from pytest_llm_assert import LLMAssert
|
|
72
|
+
|
|
73
|
+
@pytest.fixture
|
|
74
|
+
def llm():
|
|
75
|
+
return LLMAssert(model="openai/gpt-5-mini")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
# test_my_agent.py
|
|
80
|
+
def test_generated_sql_is_correct(llm):
|
|
81
|
+
sql = "SELECT name FROM users WHERE age > 21 ORDER BY name"
|
|
82
|
+
assert llm(sql, "Is this a valid SELECT query that returns names of users over 21?")
|
|
83
|
+
|
|
84
|
+
def test_error_message_is_helpful(llm):
|
|
85
|
+
error = "ValidationError: 'port' must be an integer, got 'abc'"
|
|
86
|
+
assert llm(error, "Does this explain what went wrong and how to fix it?")
|
|
87
|
+
|
|
88
|
+
def test_summary_captures_key_points(llm):
|
|
89
|
+
summary = generate_summary(document)
|
|
90
|
+
assert llm(summary, "Does this mention the contract duration and parties involved?")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Setup
|
|
94
|
+
|
|
95
|
+
Works out of the box with cloud identity — no API keys to manage:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Azure (Entra ID)
|
|
99
|
+
export AZURE_API_BASE=https://your-resource.openai.azure.com
|
|
100
|
+
az login
|
|
101
|
+
|
|
102
|
+
# Google Cloud (Vertex AI)
|
|
103
|
+
gcloud auth application-default login
|
|
104
|
+
|
|
105
|
+
# AWS (Bedrock)
|
|
106
|
+
aws configure # Uses IAM credentials
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Supports 100+ providers via [LiteLLM](https://docs.litellm.ai/docs/providers) — including API key auth for OpenAI, Anthropic, Ollama, and more.
|
|
110
|
+
|
|
111
|
+
## Documentation
|
|
112
|
+
|
|
113
|
+
- **[Configuration](docs/configuration.md)** — All providers, CLI options, environment variables
|
|
114
|
+
- **[API Reference](docs/api-reference.md)** — Full API documentation
|
|
115
|
+
- **[Comparing Judge Models](docs/comparing-models.md)** — Evaluate which LLM works best for your assertions
|
|
116
|
+
- **[Examples](examples/)** — Working pytest examples
|
|
117
|
+
|
|
118
|
+
## Related
|
|
119
|
+
|
|
120
|
+
- **[pytest-aitest](https://github.com/sbroenne/pytest-aitest)** — Full framework for testing MCP servers, CLIs, and AI agents
|
|
121
|
+
- **[Contributing](CONTRIBUTING.md)** — Development setup and guidelines
|
|
122
|
+
|
|
123
|
+
## Requirements
|
|
124
|
+
|
|
125
|
+
- Python 3.11+
|
|
126
|
+
- pytest 8.0+
|
|
127
|
+
- An LLM (OpenAI, Azure, Anthropic, etc.) or local [Ollama](https://ollama.ai/)
|
|
128
|
+
|
|
129
|
+
## Security
|
|
130
|
+
|
|
131
|
+
- **Sensitive data**: Test content is sent to LLM providers — consider data policies
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|