Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
06857d5
Moved TestRow into its own file.
gaurav Jan 8, 2026
a0325b6
Added /.env to .gitignore.
gaurav Jan 8, 2026
0009dc0
Implemented basic GitHub issue testing (but it doesn't work at all).
gaurav Jan 8, 2026
f297735
Check for a GitHub Authentication Token.
gaurav Jan 12, 2026
9b96675
Add support for `--issue` to specify one or more GitHub issues to check.
gaurav Jan 12, 2026
97bb7a6
Cleaned up some code.
gaurav Jan 12, 2026
ed8f1db
Sped up tests, made things work better.
gaurav Jan 12, 2026
f0342ce
Fixed some issues.
gaurav Jan 12, 2026
ebac7ab
It works! But it shouldn't. Cross that bridge later etc.
gaurav Jan 12, 2026
05b767e
Various improvements.
gaurav Jan 12, 2026
15b28d1
Various improvements.
gaurav Jan 12, 2026
a6845a3
Got rid of xfail system (too much bother).
gaurav Jan 12, 2026
54001bb
Incorporated issue state into outputs.
gaurav Jan 12, 2026
150f4a6
Better?
gaurav Jan 12, 2026
92821bf
Nope, still too messy.
gaurav Jan 12, 2026
9a4a22c
Added some NameRes tests.
gaurav Jan 15, 2026
2a610a4
Merge branch 'main' into add-github-issue-tests
gaurav Feb 15, 2026
0848de4
Reorganized test files.
gaurav Feb 16, 2026
127cca1
Don't need __init__.py in top-level src directory.
gaurav Feb 16, 2026
b7d2786
Merge branch 'main' into add-github-issue-tests
gaurav Feb 18, 2026
b91609f
Moved NodeNorm/NameRes into own files.
gaurav Feb 19, 2026
8a08e9a
Moved sources into separate directories.
gaurav Feb 19, 2026
1f84aea
Updated CLAUDE.md in line with updated code.
gaurav Feb 19, 2026
31b4436
Claude suggested moving blocklist code into src/ so we did.
gaurav Feb 19, 2026
6b60325
Added blocklist.py where a lot of the blocklist code has moved.
gaurav Feb 19, 2026
ac41e08
Refactor GitHub issue assertions into a dedicated package.
gaurav Feb 19, 2026
ffbc70f
Use pytest subtests for GitHub issue tests so all assertions run inde…
gaurav Feb 20, 2026
1524b27
Avoid slow GitHub API calls when building issue IDs.
gaurav Feb 20, 2026
9a19e45
Cleaned up some Claude code.
gaurav Feb 20, 2026
0ec9e20
Refactor assertions into a proper framework for easy authoring
gaurav Feb 20, 2026
ddaa14f
Auto-generate assertions/README.md from handler class attributes
gaurav Feb 20, 2026
4ed6091
Speed up GitHub issues test collection with pytest_generate_tests hook
gaurav Feb 21, 2026
c63e2d1
Parallelize GitHub issues tests with pytest-xdist
gaurav Feb 21, 2026
75abe00
Cache Google Sheet CSV to disk so xdist workers share one download
gaurav Feb 21, 2026
3bf169e
Fix non-deterministic test ordering under pytest-xdist
gaurav Feb 21, 2026
93753b0
Cleaned up code a bit.
gaurav Feb 21, 2026
2e3b93a
Improved outputs.
gaurav Feb 21, 2026
db7933b
Always download fresh Google Sheet data on each test run
gaurav Feb 21, 2026
768cf91
xfail open GitHub issues so failures don't block CI
gaurav Feb 21, 2026
6ee7441
Wipe GitHub issues cache at the start of every test run
gaurav Feb 21, 2026
74c5e35
Add system tests for invalid BabelTest assertion name detection
gaurav Feb 21, 2026
33aa773
Report failing subtests of open issues as XFAIL instead of FAIL
gaurav Feb 28, 2026
d238f38
Improved outputs.
gaurav Feb 28, 2026
8807972
Speed up GitHub issues test collection via Search API
gaurav Feb 28, 2026
056e168
Fail hard on unknown assertion types instead of XFAIL
gaurav Mar 1, 2026
79fab58
Removed default repo list.
gaurav Mar 1, 2026
fc158e4
Add DoesNotResolveWith assertion handler
gaurav Mar 1, 2026
4b77e98
Fixed Claude typo.
gaurav Mar 1, 2026
d3fb921
Improve error message.
gaurav Mar 1, 2026
4d272f1
Add HasLabel assertion handler
gaurav Mar 1, 2026
a9c0842
Fixed typo in my code.
gaurav Mar 1, 2026
4b6ea91
XPASS tests now correctly complain.
gaurav Mar 1, 2026
91782a2
Merge branch 'main' into add-github-issue-tests
gaurav Mar 5, 2026
8414350
Regenerated BabelTest assertions documentation.
gaurav Mar 6, 2026
1c75b08
Fixed timeout.
gaurav Mar 6, 2026
3eeeccf
Add unit test marker and GitHub Actions workflow for PRs
gaurav Mar 6, 2026
bccde07
Potential fix for pull request finding
gaurav Mar 15, 2026
f733858
Potential fix for pull request finding
gaurav Mar 15, 2026
79c01f7
Potential fix for pull request finding
gaurav Mar 15, 2026
9163671
Potential fix for pull request finding
gaurav Mar 15, 2026
79a0b5c
Potential fix for pull request finding
gaurav Mar 15, 2026
8e90722
Potential fix for pull request finding
gaurav Mar 15, 2026
4a399e6
Potential fix for pull request finding
gaurav Mar 15, 2026
224cd42
Fix CURIE prewarming to only normalize CURIE parameters
gaurav Mar 15, 2026
2628f50
Potential fix for pull request finding
gaurav Mar 15, 2026
32248b2
Move pytest marker config from pyproject.toml to tests/pytest.ini
gaurav Mar 15, 2026
c175f67
Tweaked error message.
gaurav Mar 15, 2026
1db38aa
Simplify: remove dead code and minor cleanup
gaurav Mar 15, 2026
2251884
Handle corrupted GitHub issues cache file gracefully
gaurav Mar 15, 2026
90bc845
Replace print() with debug logging in SearchByNameHandler
gaurav Mar 15, 2026
d474b18
Potential fix for pull request finding
gaurav Mar 16, 2026
14d230c
Fixed comment.
gaurav Mar 16, 2026
ae9ed8d
Move pytest config from tests/pytest.ini to pyproject.toml
gaurav Mar 16, 2026
dc51c0b
Updated pytest to 9.0+ so we can use subtests.
gaurav Mar 16, 2026
552d53a
Move GitHub repo list from conftest.py to targets.ini [DEFAULT]
gaurav Mar 16, 2026
2de6e09
Updated uv.lock.
gaurav Mar 16, 2026
870f1f9
Document param_set/param_sets terminology across assertions package
gaurav Mar 16, 2026
d6077ea
Reject extra params in HasLabel and SearchByName assertions
gaurav Mar 16, 2026
d7fde85
Add unit test documenting yaml.YAMLError on malformed YAML block
gaurav Mar 16, 2026
688ef36
Add TestEmptyOrNullBabelTests to document current behaviour for empty…
gaurav Mar 16, 2026
a029093
Add unit tests for issue_has_tests() and get_issues_with_tests()
gaurav Mar 16, 2026
fd44d66
Simplify: remove dead code, fix string parsing, rename fixture
gaurav Apr 1, 2026
0c46ce9
Handle missing labels in NodeNorm.
gaurav Apr 1, 2026
aa94099
Fixed level lookup in NodeNorm result.
gaurav Apr 1, 2026
ab72ae4
Merge branch 'main' into add-github-issue-tests
gaurav Apr 23, 2026
4f74880
Reverted NameRes to Solr instead of ElasticSearch.
gaurav Apr 23, 2026
714d4bb
Reconfigured ci-es.
gaurav Apr 27, 2026
1e9c42f
Changed Biolink Type param to a list.
gaurav Apr 30, 2026
5ee0efa
Add csv-to-babeltests CLI for converting CSV assets into BabelTests Y…
gaurav May 4, 2026
6d5d593
Add pytest-subtests dependency
gaurav May 5, 2026
b0a4dc0
Add request timeouts and fix bulk_lookup error message
gaurav May 5, 2026
65236d6
Validate Google Sheet HTTP response before caching
gaurav May 5, 2026
5150703
Fix wiki syntax parsing: allow assertion-name-only and warn on unreso…
gaurav May 5, 2026
da94577
Clean up lock files on pytest startup and fix incomplete comment
gaurav May 5, 2026
37d1da6
Fix CI unit-test workflow: restrict paths and inject GITHUB_TOKEN
gaurav May 5, 2026
f125cd5
Move curie_params overrides after class attributes in assertion handlers
gaurav May 5, 2026
7eeafde
Fix param-aware cache keys in CachedNodeNorm and CachedNameRes
gaurav May 8, 2026
e8c4e6f
Improve robustness of GitHub issue parsing and fetching
gaurav May 8, 2026
f6088ad
Fix GitHub issues test harness: lazy dotenv, xfail clarity, missing _…
gaurav May 8, 2026
b7146b8
Fix two bugs surfaced by Copilot review
gaurav May 8, 2026
576fa0f
Fix unbounded logger growth in GitHubIssueTest
gaurav May 8, 2026
999240f
Merge branch 'add-github-issue-tests' of github.com:TranslatorSRI/bab…
gaurav May 8, 2026
be3c09b
Fixed endpoint for NameRes blocklist.
gaurav May 8, 2026
4250f15
Fix four issues from Opus code review of PR #67
gaurav May 11, 2026
e808947
Catch expired GitHub token and fail only the GitHub issue tests
gaurav May 12, 2026
39e4e0e
Fix bugs and clean up code quality from simplify review
gaurav May 17, 2026
692418a
Fix three bugs identified in PR #67 review
gaurav May 17, 2026
09f9a84
Potential fix for pull request finding
gaurav May 18, 2026
d873d4a
Removed unused import.
gaurav May 18, 2026
bbba0d9
Removed unused import.
gaurav May 18, 2026
27e45ec
Potential fix for pull request finding
gaurav May 18, 2026
a329eb0
Add test documenting YAML scalar assertion param handling
gaurav May 18, 2026
52ef896
Merge main into add-github-issue-tests, resolving blocklist conflicts
gaurav Jun 10, 2026
063975d
Simplify assertion loop logic and YAML param normalization
gaurav Jun 10, 2026
e36334f
Simplify test config cleanup and GitHub issue caching
gaurav Jun 10, 2026
e1ee783
Keep open-issue assertion failures inside the xfail family
gaurav Jun 10, 2026
adb7829
Make the {{BabelTest|...}} wiki marker case-insensitive
gaurav Jun 10, 2026
03e0c6b
Run GitHub-issue unit tests without a GITHUB_TOKEN
gaurav Jun 10, 2026
e322040
Validate CURIEs before warming the NodeNorm cache
gaurav Jun 10, 2026
a9ec8e4
Expire the Google Sheet CSV cache after an hour
gaurav Jun 10, 2026
7e58ba7
Limit bare pytest collection to the tests directory
gaurav Jun 10, 2026
af19a1e
Correct Repositories comment in targets.ini
gaurav Jun 10, 2026
0a20287
Skip GitHub issue fetch when -m deselects the test
gaurav Jun 10, 2026
2a3085a
Enforce 2+ CURIE arity in ResolvesWith/DoesNotResolveWith
gaurav Jun 10, 2026
f0c6cb8
Avoid KeyError in normalize_curie if NodeNorm omits a CURIE
gaurav Jun 10, 2026
c7b9da9
Wire SearchByName top-N from targets.ini NameResXFailIfInTop
gaurav Jun 10, 2026
24ed4f4
Extract deselected_by_markexpr into a shared helper
gaurav Jun 10, 2026
e983020
Defer Google Sheet downloads so -m unit stays offline
gaurav Jun 10, 2026
d71ae23
Validate babel_tests YAML shape with clear errors
gaurav Jun 24, 2026
add0848
Guard against empty NodeNorm type list in assertion messages
gaurav Jun 24, 2026
c0ddd7b
Use a module-local YAML dumper in csv_to_babeltests
gaurav Jun 24, 2026
1adf194
Document testing/repo gotchas in CLAUDE.md
gaurav Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Tests

on:
pull_request:

jobs:
unit-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v6

- name: Run unit tests
Comment thread
gaurav marked this conversation as resolved.
env:
GITHUB_TOKEN: ${{ github.token }}
run: uv run pytest -m unit -v
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Ignore the root .env file.
/.env

# Ignore all data files.
data/

Expand Down
45 changes: 40 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@ pytest --target all # Run against all targets in targets.ini
pytest --category "Unit Tests" # Filter by Google Sheet category
pytest --category-exclude "Slow" # Exclude a category
pytest tests/nodenorm/test_nodenorm_from_gsheet.py # Run a specific test file
pytest tests/nodenorm/test_nodenorm_from_gsheet.py -k "row=42" # Run a specific test row
pytest -m unit # Offline unit suite (no network/token) — what CI runs on PRs
```

To run a single Google Sheet row, pass its full node ID (NOT `-k "row=42"` — pytest's
`-k` expression parser rejects the `=`):

```bash
pytest "tests/nodenorm/test_nodenorm_from_gsheet.py::test_normalization[dev-gsheet:row=42]"
```

### Code Formatting
Expand All @@ -46,21 +53,31 @@ cd website && npm install && npm run dev # Dev server at localhost:4321

## Architecture

### Library (`src/babel_validation/`)

Shared library code used by the tests and potentially other consumers.

- `core/testrow.py` — `TestRow` dataclass (models a single Google Sheet test row), `TestStatus` enum, `TestResult` dataclass
- `services/nodenorm.py` — `CachedNodeNorm`: wraps the NodeNorm `get_normalized_nodes` API with per-instance caching
- `services/nameres.py` — `CachedNameRes`: wraps the NameRes `lookup`/`bulk-lookup` APIs with per-instance caching
- `sources/google_sheets/google_sheet_test_cases.py` — `GoogleSheetTestCases`: downloads and parses the shared Google Sheet into `TestRow` instances and pytest `ParameterSet` lists
- `sources/github/github_issues_test_cases.py` — `GitHubIssueTest` and `GitHubIssuesTestCases`: pull test cases embedded in GitHub issues (wiki or YAML syntax) and evaluate them against NodeNorm/NameRes

### Test Framework (`tests/`)

The core of this project. Tests validate NodeNorm and NameRes services across multiple deployment environments.

**Target system:** `tests/targets.ini` defines endpoints for each environment (dev, prod, test, ci, exp, localhost). Tests use `target_info` fixture to get URLs. The `conftest.py` parametrizes tests across targets via `--target` CLI option; default is `dev`.

**Google Sheet integration:** ~2000+ test cases are pulled from a [shared Google Sheet](https://docs.google.com/spreadsheets/d/11zebx8Qs1Tc3ShQR9nh4HRW8QSoo8k65w_xIaftN0no/). `tests/common/google_sheet_test_cases.py` fetches and parses these into `TestRow` dataclasses. Rows marked as not expected to pass are wrapped with `pytest.mark.xfail(strict=True)`. Tests are parametrized by row, with IDs like `gsheet:row=42`.
**Google Sheet integration:** ~2000+ test cases are pulled from a [shared Google Sheet](https://docs.google.com/spreadsheets/d/11zebx8Qs1Tc3ShQR9nh4HRW8QSoo8k65w_xIaftN0no/). `src/babel_validation/sources/google_sheets/google_sheet_test_cases.py` fetches and parses these into `TestRow` dataclasses. Rows marked as not expected to pass are wrapped with `pytest.mark.xfail(strict=True)`. Tests are parametrized by row, with IDs like `gsheet:row=42`.

**Category filtering:** Google Sheet rows have a Category column. The `test_category` fixture (from conftest.py) returns a callable that tests use to `pytest.skip()` rows not matching `--category`/`--category-exclude` filters.

**Test modules:**
- `tests/nodenorm/` — NodeNorm tests (normalization accuracy, preferred IDs/labels, Biolink types, conflation, descriptions, OpenAPI spec, setid endpoint)
- `tests/nameres/` — NameRes tests (label lookup, autocomplete, Biolink type filtering, blocklist, taxon_specific flag)
- `tests/nodenorm/by_issue/` — Tests tied to specific GitHub issues
- `tests/common/` — Shared utilities (`GoogleSheetTestCases`, `TestRow`)
- `tests/nodenorm/by_issue/` — Per-issue regression tests for NodeNorm (hand-written)
- `tests/github_issues/` — Dynamically-generated tests pulled from GitHub issue bodies via `GitHubIssuesTestCases`

### Web Applications

Expand All @@ -79,4 +96,22 @@ When writing new tests:
- Use the `target_info` fixture to get NodeNorm/NameRes URLs from targets.ini
- For Google Sheet-based tests, parametrize with `gsheet.test_rows()` and use the `test_category` fixture for category filtering
- Use `pytest.mark.xfail(strict=True)` for known failures (strict=True means unexpected passes also fail)
- Issue-specific tests go in `tests/nodenorm/by_issue/` or `tests/github_issues/`
- Hand-written per-issue regression tests go in `tests/nodenorm/by_issue/`
- GitHub-issue-driven tests are picked up automatically by `tests/github_issues/test_github_issues.py` via `GitHubIssuesTestCases`
- Import shared classes from `src.babel_validation.*` (e.g. `from src.babel_validation.services.nodenorm import CachedNodeNorm`)

## Gotchas (learned the hard way)

- **Offline vs. networked tests.** `pytest -m unit` is the offline suite CI runs on PRs (no
network, no `GITHUB_TOKEN`). Network-backed modules (Google Sheet, GitHub issues) defer all
fetching to `pytest_generate_tests` and call `tests/_pytest_helpers.deselected_by_markexpr`
so a marker-deselected run never hits the network. If you add a module that fetches at
import/collection time, replicate that pattern or you'll break `-m unit`.
- **`src/babel_validation` is importable only because** `[tool.hatch.build.targets.wheel]` in
`pyproject.toml` packages `src/`. Imports use the full `src.babel_validation.*` path.
- **Black is not strictly enforced** — `black --check` flags much of the existing tree. Match
the surrounding style of the file you're editing; don't mass-reformat (it creates huge,
review-hostile diffs).
- **Commits are signed via 1Password's SSH agent** (`op-ssh-sign`). It can lock mid-session;
a `failed to fill whole buffer` / `failed to write commit object` error means 1Password
needs unlocking, not a git problem.
31 changes: 30 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,41 @@ readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"black>=25.9.0",
"click>=8.1",
"pyyaml>=6.0",
"requests>=2.32.5",
"tqdm>=4.67.1",
"filelock",
"deepdiff>=8.6.1",
"python-dotenv>=0.9.9",
"openapi-spec-validator>=0.7.2",
"pytest>=8.4.2",
"pygithub>=2.8.1",
"pytest>=9.0.2",
"pytest-timeout>=2.4.0",
"pytest-xdist[psutil]",
Comment thread
gaurav marked this conversation as resolved.
Comment thread
gaurav marked this conversation as resolved.
Comment thread
gaurav marked this conversation as resolved.
"pytest-subtests",
]

[project.urls]
Repository = "https://github.com/TranslatorSRI/babel-validation"

[project.scripts]
csv-to-babeltests = "src.babel_validation.tools.csv_to_babeltests:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
# Package the entire `src/` directory so existing imports
# (`from src.babel_validation.X import Y`) continue to work after install.
packages = ["src"]

[tool.pytest.ini_options]
# Without testpaths, a bare `pytest` would also scan the website directories
# (including node_modules) during collection.
testpaths = ["tests"]
timeout = 300
markers = [
"unit: unit tests that do not require network access",
]
File renamed without changes.
Empty file.
243 changes: 243 additions & 0 deletions src/babel_validation/assertions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
<!-- AUTO-GENERATED — do not edit by hand.
Regenerate with: uv run python -m src.babel_validation.assertions.gen_docs -->

# BabelTest Assertion Types

This package defines the assertion types that can be embedded in GitHub issue bodies and evaluated against the NodeNorm and NameRes services.

## Embedding Tests in Issues

Two syntaxes are supported:

**Wiki syntax** (one assertion per line):
```
{{BabelTest|AssertionType|param1|param2|...}}
```

**YAML syntax** (multiple assertions, multiple param sets):
````
```yaml
babel_tests:
AssertionType:
- param1
- [param1, param2]
```
````

Assertion names are case-insensitive, as is the `{{BabelTest|...}}` marker itself.

## Param Sets

Each assertion can be invoked with one or more **param sets** — independent groups of
parameters that are each evaluated separately.

- **Wiki syntax** — each `{{BabelTest|...}}` line is one param set.
- **YAML syntax** — each list entry under an assertion key is one param set; a bare string
is a single-element param set, a YAML list is a multi-element param set.

The meaning of each element in a param set depends on the assertion type (see below).
For most assertions the elements are CURIEs; for `HasLabel` the second element is a
label string; for `ResolvesWithType` the first element is a Biolink type.

---

## NodeNorm Assertions

These assertions test the [NodeNorm](https://nodenorm.transltr.io/docs) service.

### Resolves

**Applies to:** NodeNorm

Each CURIE in each param_set must resolve to a non-null result in NodeNorm.

**Parameters:** One or more CURIEs per param_set.

**Wiki syntax:**
```
{{BabelTest|Resolves|CHEBI:15365}}
{{BabelTest|Resolves|MONDO:0005015|DOID:9351}}
```

**YAML syntax:**
```yaml
babel_tests:
Resolves:
- CHEBI:15365
- [MONDO:0005015, DOID:9351]
```

---

### DoesNotResolve

**Applies to:** NodeNorm

Each CURIE in each param_set must fail to resolve (return null) in NodeNorm. Use this to confirm that an identifier is intentionally not normalizable.

**Parameters:** One or more CURIEs per param_set.

**Wiki syntax:**
```
{{BabelTest|DoesNotResolve|FAKENS:99999}}
```

**YAML syntax:**
```yaml
babel_tests:
DoesNotResolve:
- FAKENS:99999
```

---

### ResolvesWith

**Applies to:** NodeNorm

All CURIEs within each param_set must resolve to the identical normalized result. Use this to assert that two identifiers are equivalent.

**Parameters:** Two or more CURIEs per param_set. All must resolve to the same result.

**Wiki syntax:**
```
{{BabelTest|ResolvesWith|CHEBI:15365|PUBCHEM.COMPOUND:1}}
```

**YAML syntax:**
```yaml
babel_tests:
ResolvesWith:
- [CHEBI:15365, PUBCHEM.COMPOUND:1]
- [MONDO:0005015, DOID:9351]
```

---

### DoesNotResolveWith

**Applies to:** NodeNorm

The CURIEs within each param_set must NOT all resolve to the same normalized result. Use this to assert that two identifiers are intentionally distinct entities.

**Parameters:** Two or more CURIEs per param_set. They must not all resolve to the same result.

**Wiki syntax:**
```
{{BabelTest|DoesNotResolveWith|CHEBI:15365|CHEBI:16856}}
```

**YAML syntax:**
```yaml
babel_tests:
DoesNotResolveWith:
- [CHEBI:15365, CHEBI:16856]
```

---

### HasLabel

**Applies to:** NodeNorm

The CURIE must resolve in NodeNorm and its primary label (id.label) must match the expected label exactly (case-sensitive).

**Parameters:** Exactly two elements per param_set: a CURIE, then the expected label string.

**Wiki syntax:**
```
{{BabelTest|HasLabel|CHEBI:15365|aspirin}}
```

**YAML syntax:**
```yaml
babel_tests:
HasLabel:
- [CHEBI:15365, aspirin]
```

---

### ResolvesWithType

**Applies to:** NodeNorm

Each param_set must have at least two elements: the first is the expected Biolink type (e.g. 'biolink:Gene'), and the remainder are CURIEs that must resolve with that type.

**Parameters:** Each param_set: first element is the expected Biolink type (e.g. `biolink:Gene`), remaining elements are CURIEs.

**Wiki syntax:**
```
{{BabelTest|ResolvesWithType|biolink:Gene|NCBIGene:1}}
```

**YAML syntax:**
```yaml
babel_tests:
ResolvesWithType:
- [biolink:Gene, NCBIGene:1, HGNC:5]
```

---

## NameRes Assertions

These assertions test the [NameRes](https://name-lookup.transltr.io/docs) service.

### SearchByName

**Applies to:** NameRes

Each param_set must have at least two elements: a search query string and an expected CURIE. The test passes if the CURIE's normalized identifier appears within the top N results (default N=5) when NameRes looks up the search query.

**Parameters:** Each param_set: the **search query string** and the **expected CURIE**. The CURIE is normalized via NodeNorm (drug/chemical conflation enabled) before matching.

**Wiki syntax:**
```
{{BabelTest|SearchByName|water|CHEBI:15377}}
```

**YAML syntax:**
```yaml
babel_tests:
SearchByName:
- [water, CHEBI:15377]
- [diabetes, MONDO:0005015]
```

---

## Special Assertions

### Needed

**Applies to:** NodeNorm and NameRes

Marks an issue as needing a test — always fails as a reminder to add real assertions.

**Wiki syntax:**
```
{{BabelTest|Needed}}
```

**YAML syntax:**
```yaml
babel_tests:
Needed:
- placeholder
```

---

## Adding a New Assertion Type

1. Choose the right module:
- `nodenorm.py` — for NodeNorm-only assertions (subclass `NodeNormTest`, override `test_param_set`)
- `nameres.py` — for NameRes-only assertions (subclass `NameResTest`, override `test_param_set`)
- `common.py` — for assertions that apply to both services (subclass `AssertionHandler`, override `test_with_nodenorm` and/or `test_with_nameres`)

2. Define the class with `NAME`, `DESCRIPTION`, `PARAMETERS`, `WIKI_EXAMPLES`, `YAML_PARAMS`, and `test_param_set()` (or both `test_with_*` methods for `AssertionHandler` subclasses).

3. Import it in `__init__.py` and add an instance to `ASSERTION_HANDLERS`.

4. Run `uv run python -m src.babel_validation.assertions.gen_docs` to regenerate `README.md`.
Loading
Loading