Skip to content

Commit d550274

Browse files
authored
Merge pull request #57 from ixc/50_add_performance_tests
50 add performance tests
2 parents a6c869e + 6c0e239 commit d550274

7 files changed

Lines changed: 102 additions & 2 deletions

File tree

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ on:
88
permissions:
99
checks: write
1010
contents: write
11+
# deployments permission to deploy GitHub pages website
12+
deployments: write
1113
pull-requests: write
1214

1315

@@ -85,3 +87,39 @@ jobs:
8587
echo "Coverage Tests - ${{ steps.coverageComment.outputs.tests }}"
8688
echo "Coverage Time - ${{ steps.coverageComment.outputs.time }}"
8789
echo "Not Success Test Info - ${{ steps.coverageComment.outputs.notSuccessTestInfo }}"
90+
91+
- name: Run benchmarks
92+
run: |
93+
pytest -m benchmark --benchmark-json=./output.json
94+
95+
- name: Download previous benchmark data
96+
uses: actions/cache@v4
97+
with:
98+
path: ./cache
99+
key: ${{ runner.os }}-benchmark
100+
101+
- name: Publish benchmark results
102+
uses: benchmark-action/github-action-benchmark@v1
103+
if: github.event_name != 'pull_request'
104+
with:
105+
tool: 'pytest'
106+
auto-push: true
107+
comment-always: true
108+
output-file-path: output.json
109+
github-token: ${{ secrets.GITHUB_TOKEN }}
110+
comment-on-alert: true
111+
save-data-file: true
112+
summary-always: true
113+
114+
- name: Comment on benchmark results without publishing
115+
uses: benchmark-action/github-action-benchmark@v1
116+
with:
117+
tool: 'pytest'
118+
auto-push: false
119+
github-token: ${{ secrets.GITHUB_TOKEN }}
120+
comment-always: true
121+
output-file-path: output.json
122+
comment-on-alert: false
123+
save-data-file: true
124+
summary-always: true
125+
external-data-json-path: ./cache/benchmark-data.json

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ Since the `EDTFField` and the `_earliest` and `_latest` field values are set aut
401401

402402
### Running tests
403403
- From `python-edtf`, run the unit tests: `pytest`
404+
- From `python-edtf`, run `pytest -m benchmark` to run the benchmarks (published [here]( https://ixc.github.io/python-edtf/dev/bench/))
404405
- From `python-edtf/edtf_django_tests`, run the integration tests: `python manage.py test edtf_integration`
405406
- To run CI locally, use `act`, e.g. `act pull_request` or `act --pull=false --container-architecture linux/amd64`. Some steps may require a Github PAT: `act pull_request --container-architecture linux/amd64 --pull=false -s GITHUB_TOKEN=<your PAT>`
406407

dev-requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
-r requirements.txt # Include all main requirements
22
django>=4.2,<5.0
33
pytest
4+
pytest-benchmark
5+
pytest-django
46
ruff
57
pre-commit

edtf/natlang/tests.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,27 @@ def test_natlang(input_text, expected_output):
185185
assert (
186186
result == expected_output
187187
), f"Failed for input: {input_text} - expected {expected_output}, got {result}"
188+
189+
190+
@pytest.mark.benchmark
191+
@pytest.mark.parametrize(
192+
"input_text,expected_output",
193+
[
194+
("23rd Dynasty", None),
195+
("January 2008", "2008-01"),
196+
("ca1860", "1860~"),
197+
("uncertain: approx 1862", "1862%"),
198+
("January", "XXXX-01"),
199+
("Winter 1872", "1872-24"),
200+
("before approx January 18 1928", "/1928-01-18~"),
201+
("birthday in 1872", "1872"),
202+
("1270 CE", "1270"),
203+
("2nd century bce", "-01XX"),
204+
("1858/1860", "[1858, 1860]"),
205+
],
206+
)
207+
def test_benchmark_natlang(benchmark, input_text, expected_output):
208+
"""
209+
Benchmark selected natural language conversions
210+
"""
211+
benchmark(text_to_edtf, input_text)

edtf/parser/grammar.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# ruff: noqa: E402 I001
2+
3+
# It's recommended to `enablePackrat()` immediately after importing pyparsing
4+
# https://github.com/pyparsing/pyparsing/wiki/Performance-Tips
5+
6+
import pyparsing
7+
8+
pyparsing.ParserElement.enablePackrat()
9+
110
from pyparsing import (
211
Combine,
312
NotAny,
@@ -13,6 +22,7 @@
1322
)
1423
from pyparsing import Literal as L
1524

25+
1626
from edtf.parser.edtf_exceptions import EDTFParseException
1727

1828
# (* ************************** Level 0 *************************** *)

edtf/parser/tests.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,20 @@
216216
("2001-34", ("2001-04-01", "2001-06-30")),
217217
)
218218

219+
BENCHMARK_EXAMPLES = (
220+
"2001-02-03",
221+
"2008-12",
222+
"2008",
223+
"-0999",
224+
"2004-01-01T10:10:10+05:00",
225+
"-2005/-1999-02",
226+
"/2006",
227+
"?2004-%06",
228+
"[1667, 1760-12]",
229+
"Y3388E2S3",
230+
"2001-29",
231+
)
232+
219233
BAD_EXAMPLES = (
220234
# parentheses are not used for group qualification in the 2018 spec
221235
None,
@@ -340,3 +354,10 @@ def test_comparisons():
340354
assert d4 == d5
341355
assert d1 < d5
342356
assert d1 > d6
357+
358+
359+
@pytest.mark.benchmark
360+
@pytest.mark.parametrize("test_input", BENCHMARK_EXAMPLES)
361+
def test_benchmark_parser(benchmark, test_input):
362+
"""Benchmark parsing of selected EDTF strings."""
363+
benchmark(parse, test_input)

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ test = [
3939
"django>=4.2,<5.0",
4040
"pytest",
4141
"pytest-django",
42+
"pytest-benchmark",
4243
"ruff",
4344
"pre-commit",
4445
"coverage",
@@ -81,8 +82,11 @@ legacy_tox_ini = """
8182
python_files = ["tests.py", "test_*.py", "*_test.py", "*_tests.py"]
8283
python_classes = ["Test*", "*Tests"]
8384
python_functions = ["test_*"]
84-
addopts = "--ignore=edtf_django_tests/ --cov=edtf"
85-
plugins = ["pytest_cov"]
85+
markers = [
86+
"benchmark: mark a test as a benchmark",
87+
]
88+
addopts = "--ignore=edtf_django_tests/ --cov=edtf -m 'not benchmark'"
89+
plugins = ["pytest_cov", "pytest_benchmark"]
8690

8791
[tool.coverage.run]
8892
# we run the edtf_integration tests but only care about them testing fields.py in the main package

0 commit comments

Comments
 (0)