Skip to content

Commit 01879e3

Browse files
Copilotbact
andcommitted
Add corpus catalog tests and rename workflow to "Corpus Data Test"
Co-authored-by: bact <128572+bact@users.noreply.github.com>
1 parent bb11971 commit 01879e3

4 files changed

Lines changed: 186 additions & 19 deletions

File tree

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project
22
# SPDX-License-Identifier: Apache-2.0
33

4-
name: Corpus Integrity Test
4+
name: Corpus Data Test
55

66
on:
77
push:
88
paths:
9-
- ".github/workflows/corpus-integrity.yml"
9+
- ".github/workflows/corpus-data.yml"
1010
- "pythainlp/corpus/**"
1111
- "tests/corpus_integrity/**"
1212
pull_request:
1313
branches:
1414
- dev
1515
paths:
16-
- ".github/workflows/corpus-integrity.yml"
16+
- ".github/workflows/corpus-data.yml"
1717
- "pythainlp/corpus/**"
1818
- "tests/corpus_integrity/**"
1919

@@ -26,7 +26,7 @@ concurrency:
2626
cancel-in-progress: true
2727

2828
jobs:
29-
corpus-integrity:
29+
corpus-data:
3030
runs-on: ubuntu-latest
3131
permissions:
3232
contents: read
@@ -46,6 +46,12 @@ jobs:
4646
pip install --upgrade pip
4747
pip install .
4848
49+
- name: Test corpus catalog
50+
env:
51+
PYTHONIOENCODING: utf-8
52+
run: |
53+
python -m unittest discover -s tests/corpus_integrity -p "test_catalog*.py" -v
54+
4955
- name: Test built-in corpus files
5056
env:
5157
PYTHONIOENCODING: utf-8

tests/README.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,34 @@ for real-world usage:
169169
- Multi-engine robustness testing across all core tokenization engines
170170
- Very long strings that can cause performance issues (issue #893)
171171

172-
## Corpus integrity tests (corpus_integrity/)
172+
## Corpus data tests (corpus_integrity/)
173173

174-
A separate test suite that verifies the integrity, format, and parseability
175-
of corpus files in PyThaiNLP. These tests are separate from regular unit tests
176-
because they test actual file loading and parsing (not mocked) and downloadable
177-
corpus tests require network access.
174+
A separate test suite that verifies the integrity, format, parseability, and catalog
175+
functionality of corpus data in PyThaiNLP. These tests are separate from regular unit tests
176+
because they test actual file loading and parsing (not mocked), downloadable corpus tests
177+
require network access, and they verify corpus catalog operations.
178178

179-
For detailed information about corpus integrity tests, see:
179+
For detailed information about corpus data tests, see:
180180
[tests/corpus_integrity/README.md](corpus_integrity/README.md)
181181

182-
The corpus integrity tests are triggered automatically via GitHub Actions
182+
The corpus data tests are triggered automatically via GitHub Actions
183183
when changes are made to `pythainlp/corpus/**` or `tests/corpus_integrity/**`.
184184

185-
**Run corpus integrity tests:**
185+
**Key characteristics:**
186+
- Tests actual file loading and parsing (not mocked)
187+
- Verifies corpus data format and structure
188+
- Tests corpus catalog download and query
189+
- Only runs when corpus files or corpus code changes
190+
- Includes tests for both built-in and downloadable corpus files
191+
192+
**Run corpus data tests:**
186193
```shell
187194
python -m unittest tests.corpus_integrity
188195
```
196+
197+
Or run specific test files:
198+
```shell
199+
python -m unittest tests.corpus_integrity.test_catalog
200+
python -m unittest tests.corpus_integrity.test_builtin_corpus
201+
python -m unittest tests.corpus_integrity.test_downloadable_corpus
202+
```

tests/corpus_integrity/README.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
# Corpus Integrity Tests
1+
# Corpus Data Tests
22

3-
This directory contains tests that verify the integrity, format, and parseability of corpus files in PyThaiNLP.
3+
This directory contains tests that verify the integrity, format, parseability, and catalog functionality of corpus data in PyThaiNLP.
44

55
## Purpose
66

77
These tests are separate from regular unit tests because:
88
1. They test actual file loading and parsing (not mocked)
99
2. Downloadable corpus tests require network access and can be slow
1010
3. They verify corpus data format and structure
11-
4. They should only run when corpus files or corpus code changes
11+
4. They test corpus catalog download and query functionality
12+
5. They should only run when corpus files or corpus code changes
1213

1314
## Test Categories
1415

16+
### Corpus Catalog Tests (`test_catalog.py`)
17+
18+
Tests corpus catalog functionality:
19+
- Catalog download from remote server
20+
- Catalog URL and path validation
21+
- Catalog JSON structure verification
22+
- Querying specific corpus details
23+
- Version information validation
24+
25+
**Run time:** < 1 second
26+
1527
### Built-in Corpus Tests (`test_builtin_corpus.py`)
1628

1729
Tests corpus files that are included in the package:
@@ -32,11 +44,16 @@ Tests corpus files that need to be downloaded:
3244

3345
## Running Tests
3446

35-
### Run all corpus integrity tests:
47+
### Run all corpus data tests:
3648
```bash
3749
python -m unittest discover -s tests/corpus_integrity -v
3850
```
3951

52+
### Run only catalog tests:
53+
```bash
54+
python -m unittest tests.corpus_integrity.test_catalog -v
55+
```
56+
4057
### Run only built-in corpus tests:
4158
```bash
4259
python -m unittest tests.corpus_integrity.test_builtin_corpus -v
@@ -49,7 +66,7 @@ python -m unittest tests.corpus_integrity.test_downloadable_corpus -v
4966

5067
## CI Integration
5168

52-
The corpus integrity tests run automatically via GitHub Actions workflow (`.github/workflows/corpus-integrity.yml`) when:
69+
The corpus data tests run automatically via GitHub Actions workflow (`.github/workflows/corpus-data.yml`) when:
5370
- Changes are made to `pythainlp/corpus/**`
5471
- Changes are made to `tests/corpus_integrity/**`
5572
- The workflow file itself is modified
@@ -62,17 +79,19 @@ Each test verifies:
6279
3. **Non-empty**: Contains actual data
6380
4. **Format validity**: Data structure matches expected format
6481
5. **Content validity**: Contains expected content (e.g., Thai characters)
82+
6. **Catalog functionality**: Catalog can be downloaded and queried correctly
6583

6684
## Adding New Tests
6785

6886
When adding a new corpus file or function to `pythainlp.corpus`:
6987
1. Add a test to `test_builtin_corpus.py` if it's included in the package
7088
2. Add a test to `test_downloadable_corpus.py` if it requires download
71-
3. Verify the test catches format errors by temporarily breaking the corpus
89+
3. Add a test to `test_catalog.py` if it involves catalog operations
90+
4. Verify the test catches format errors by temporarily breaking the corpus
7291

7392
## Relationship to Unit Tests
7493

7594
- **Unit tests** (`tests/core/test_corpus.py`): Use mocks for speed, test code logic
76-
- **Corpus integrity tests** (this directory): Use real data, test file integrity
95+
- **Corpus data tests** (this directory): Use real data, test file integrity and catalog
7796

7897
Both test suites are important and complementary.
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# SPDX-FileCopyrightText: 2016-2026 PyThaiNLP Project
2+
# SPDX-FileType: SOURCE
3+
# SPDX-License-Identifier: Apache-2.0
4+
"""
5+
Test corpus catalog download and query functionality.
6+
7+
These tests verify that the corpus catalog can be downloaded from
8+
the remote server and queried correctly.
9+
"""
10+
11+
import unittest
12+
13+
from pythainlp.corpus import (
14+
corpus_db_path,
15+
corpus_db_url,
16+
get_corpus_db,
17+
get_corpus_db_detail,
18+
)
19+
20+
21+
class CorpusCatalogTestCase(unittest.TestCase):
22+
"""Test corpus catalog functionality."""
23+
24+
def test_catalog_url(self):
25+
"""Test that corpus catalog URL is valid and accessible."""
26+
url = corpus_db_url()
27+
self.assertIsNotNone(url)
28+
self.assertIsInstance(url, str)
29+
self.assertTrue(url.startswith("https://"))
30+
self.assertIn("pythainlp", url.lower())
31+
32+
def test_catalog_path(self):
33+
"""Test that corpus catalog path is valid."""
34+
path = corpus_db_path()
35+
self.assertIsNotNone(path)
36+
self.assertIsInstance(path, str)
37+
self.assertTrue(path.endswith("db.json"))
38+
39+
def test_catalog_download(self):
40+
"""Test that corpus catalog can be downloaded from remote server."""
41+
url = corpus_db_url()
42+
catalog = get_corpus_db(url)
43+
44+
self.assertIsNotNone(catalog, "Catalog download should succeed")
45+
self.assertTrue(hasattr(catalog, "json"), "Catalog should have json method")
46+
self.assertTrue(
47+
hasattr(catalog, "status_code"), "Catalog should have status_code"
48+
)
49+
50+
def test_catalog_structure(self):
51+
"""Test that downloaded catalog has valid JSON structure."""
52+
url = corpus_db_url()
53+
catalog = get_corpus_db(url)
54+
55+
self.assertIsNotNone(catalog)
56+
catalog_data = catalog.json()
57+
58+
self.assertIsInstance(catalog_data, dict, "Catalog should be a dictionary")
59+
self.assertGreater(
60+
len(catalog_data), 0, "Catalog should contain at least one corpus"
61+
)
62+
63+
# Check that catalog entries have expected structure
64+
for corpus_name, corpus_info in list(catalog_data.items())[:5]:
65+
self.assertIsInstance(corpus_name, str)
66+
self.assertIsInstance(corpus_info, dict)
67+
self.assertIn("latest_version", corpus_info)
68+
self.assertIn("versions", corpus_info)
69+
self.assertIsInstance(corpus_info["versions"], dict)
70+
71+
def test_catalog_known_entries(self):
72+
"""Test that catalog contains known corpus entries."""
73+
url = corpus_db_url()
74+
catalog = get_corpus_db(url)
75+
76+
self.assertIsNotNone(catalog)
77+
catalog_data = catalog.json()
78+
79+
# Check for some known corpus entries
80+
# "test" is a standard test corpus that should always exist
81+
self.assertIn("test", catalog_data, "Catalog should contain 'test' corpus")
82+
83+
# Verify the test corpus has required fields
84+
test_corpus = catalog_data["test"]
85+
self.assertIn("latest_version", test_corpus)
86+
self.assertIn("versions", test_corpus)
87+
88+
def test_corpus_detail_query(self):
89+
"""Test querying details for specific corpus from local database."""
90+
# This tests the local query function
91+
# First, ensure we have a local database by attempting a download/query
92+
url = corpus_db_url()
93+
catalog = get_corpus_db(url)
94+
self.assertIsNotNone(catalog)
95+
96+
# Test querying a corpus that may exist locally
97+
# get_corpus_db_detail reads from local db.json file
98+
detail = get_corpus_db_detail("test")
99+
# Detail could be empty if not downloaded, but should return a dict
100+
self.assertIsInstance(detail, dict)
101+
102+
# Test querying non-existent corpus
103+
detail_nonexist = get_corpus_db_detail("NONEXISTENT_CORPUS_12345")
104+
self.assertIsInstance(detail_nonexist, dict)
105+
self.assertEqual(len(detail_nonexist), 0, "Non-existent corpus should return empty dict")
106+
107+
def test_catalog_version_info(self):
108+
"""Test that catalog entries contain valid version information."""
109+
url = corpus_db_url()
110+
catalog = get_corpus_db(url)
111+
112+
self.assertIsNotNone(catalog)
113+
catalog_data = catalog.json()
114+
115+
# Check version information for test corpus
116+
if "test" in catalog_data:
117+
test_corpus = catalog_data["test"]
118+
versions = test_corpus.get("versions", {})
119+
120+
self.assertIsInstance(versions, dict)
121+
if versions:
122+
# Check structure of version entries
123+
for version_key, version_info in list(versions.items())[:1]:
124+
self.assertIsInstance(version_key, str)
125+
self.assertIsInstance(version_info, dict)
126+
# Version info should have these fields
127+
self.assertIn("filename", version_info)
128+
self.assertIn("download_url", version_info)

0 commit comments

Comments
 (0)