Hemprasad Badgujar
Add bm25 prefilter stage; unify candidates cache; validate reasoning quality
cd5f9d4 Download tests/test_load.py from hembad/reranker: direct link, hf CLI and curl.
- Browser
- Download file 7.97 kB
-
https://huggingface.co/spaces/hembad/reranker/resolve/main/tests/test_load.py
- Command line
-
hf download hf://spaces/hembad/reranker/tests/test_load.py
-
curl -L -o test_load.py https://huggingface.co/spaces/hembad/reranker/resolve/main/tests/test_load.py
7.97 kB
| """Step 02 sub-phase 1 contract β load coverage, no-drop, sentinel preservation.""" | |
| from __future__ import annotations | |
| from pathlib import Path | |
| import orjson | |
| from preprocess.load import UNKNOWN_SENTINEL, load_candidates | |
| _SCHEMA_PATH = Path(__file__).resolve().parents[1] / "data" / "candidate_schema.json" | |
| # The five document arrays are kept structured (not hoisted); every other schema leaf becomes a column. | |
| _ARRAY_FIELDS = ["career_history", "education", "skills", "certifications", "languages"] | |
| def _write_jsonl(path: Path, records: list[dict]) -> Path: | |
| path.write_bytes(b"\n".join(orjson.dumps(r) for r in records)) | |
| return path | |
| def test_flatten_covers_every_schema_field(tmp_path: Path) -> None: | |
| """Adding a field to candidate_schema.json must force a new column β this guards that contract.""" | |
| schema = orjson.loads(_SCHEMA_PATH.read_bytes()) | |
| frame = load_candidates(_write_jsonl(tmp_path / "c.jsonl", [{"candidate_id": "CAND_0000001"}])) | |
| columns = set(frame.columns) | |
| assert "candidate_id" in columns | |
| for array_field in _ARRAY_FIELDS: | |
| assert array_field in columns, f"array field {array_field} missing" | |
| for profile_field in schema["properties"]["profile"]["properties"]: | |
| assert profile_field in columns, f"profile.{profile_field} not covered" | |
| for signal_field in schema["properties"]["redrob_signals"]["properties"]: | |
| if signal_field == "expected_salary_range_inr_lpa": | |
| assert {"expected_salary_min", "expected_salary_max"} <= columns | |
| else: | |
| assert signal_field in columns, f"redrob_signals.{signal_field} not covered" | |
| def test_blank_and_malformed_lines_are_skipped_not_dropped(tmp_path: Path) -> None: | |
| """Two valid records survive; a blank line and a malformed line are skipped, never abort the load.""" | |
| valid = [{"candidate_id": "CAND_0000001"}, {"candidate_id": "CAND_0000002"}] | |
| path = tmp_path / "c.jsonl" | |
| lines = [orjson.dumps(valid[0]), b"", b"{not valid json", orjson.dumps(valid[1])] | |
| path.write_bytes(b"\n".join(lines)) | |
| frame = load_candidates(path) | |
| assert frame.height == 2 | |
| assert frame["candidate_id"].to_list() == ["CAND_0000001", "CAND_0000002"] | |
| def test_unknown_sentinel_is_preserved(tmp_path: Path) -> None: | |
| """github_activity_score / offer_acceptance_rate keep their -1 'unknown' marker verbatim on load.""" | |
| record = { | |
| "candidate_id": "CAND_0000001", | |
| "redrob_signals": {"github_activity_score": -1, "offer_acceptance_rate": -1}, | |
| } | |
| frame = load_candidates(_write_jsonl(tmp_path / "c.jsonl", [record])) | |
| assert frame["github_activity_score"][0] == UNKNOWN_SENTINEL | |
| assert frame["offer_acceptance_rate"][0] == UNKNOWN_SENTINEL | |
| def test_derived_flat_lists_mirror_the_nested_arrays(tmp_path: Path) -> None: | |
| """Every nested array gets a name-only flat_* projection; assessment map β verified_skills + {name,score}.""" | |
| record = { | |
| "candidate_id": "CAND_0000001", | |
| "career_history": [ | |
| {"title": "AI Engineer", "industry": "Tech", "company_size": "51-200"}, | |
| {"title": "ML Engineer", "industry": "Fintech", "company_size": "11-50"}, | |
| ], | |
| "education": [{"institution": "IIT", "degree": "BTech", "tier": "tier_1"}], | |
| "skills": [{"name": "Python"}, {"name": "PyTorch"}], | |
| "languages": [{"language": "English"}, {"language": "Hindi"}], | |
| "certifications": [{"name": "AWS SAA"}], | |
| "redrob_signals": {"skill_assessment_scores": {"Python": 90.0}}, | |
| } | |
| row = load_candidates(_write_jsonl(tmp_path / "c.jsonl", [record])).row(0, named=True) | |
| assert row["flat_job_titles"] == ["AI Engineer", "ML Engineer"] | |
| assert row["flat_career_industries"] == ["Tech", "Fintech"] | |
| assert row["flat_company_sizes"] == ["51-200", "11-50"] | |
| assert row["flat_institutions"] == ["IIT"] | |
| assert row["flat_institution_tiers"] == ["tier_1"] | |
| assert row["flat_degrees"] == ["BTech"] | |
| assert row["flat_skills"] == ["Python", "PyTorch"] | |
| assert row["flat_languages"] == ["English", "Hindi"] | |
| assert row["flat_certifications"] == ["AWS SAA"] | |
| assert row["verified_skills"] == ["Python"] | |
| assert row["skill_assessment_scores"] == [{"name": "Python", "score": 90.0}] | |
| def test_salary_range_is_unnested(tmp_path: Path) -> None: | |
| """expected_salary_range_inr_lpa.{min,max} flatten to two scalar columns.""" | |
| record = { | |
| "candidate_id": "CAND_0000001", | |
| "redrob_signals": {"expected_salary_range_inr_lpa": {"min": 18.0, "max": 32.0}}, | |
| } | |
| frame = load_candidates(_write_jsonl(tmp_path / "c.jsonl", [record])) | |
| assert frame["expected_salary_min"][0] == 18.0 | |
| assert frame["expected_salary_max"][0] == 32.0 | |
| def test_load_uses_and_writes_cache_for_default_path(tmp_path: Path, monkeypatch) -> None: | |
| """The DEFAULT_CANDIDATES + limit=None path caches to Parquet; a later call reads the cache, not the JSONL β | |
| proven by counting how many times the JSONL is actually opened+parsed, not just comparing results.""" | |
| import preprocess.load as load_module | |
| source = _write_jsonl(tmp_path / "candidates.jsonl", [{"candidate_id": "CAND_0000001"}]) | |
| cache = tmp_path / "cache.parquet" | |
| monkeypatch.setattr(load_module, "DEFAULT_CANDIDATES", source) | |
| monkeypatch.setattr(load_module, "LOADED_CANDIDATES_CACHE", cache) | |
| real_open_text = load_module._open_text | |
| open_count = 0 | |
| def _counting_open_text(path): | |
| nonlocal open_count | |
| open_count += 1 | |
| return real_open_text(path) | |
| monkeypatch.setattr(load_module, "_open_text", _counting_open_text) | |
| assert not cache.exists() | |
| first = load_candidates(source) # limit=None, path == DEFAULT_CANDIDATES β cache-eligible; a real parse | |
| assert cache.exists() | |
| assert first["candidate_id"].to_list() == ["CAND_0000001"] | |
| assert open_count == 1 | |
| second = load_candidates(source) # must be served from the Parquet cache β the JSONL is NOT reopened | |
| assert second["candidate_id"].to_list() == ["CAND_0000001"] | |
| assert open_count == 1 # unchanged β proves the second call never touched the source file at all | |
| def test_load_cache_not_used_for_custom_path_or_limit(tmp_path: Path, monkeypatch) -> None: | |
| """A custom path or a limit'd read must NEVER use/pollute the cache β it isn't the real full dataset.""" | |
| import preprocess.load as load_module | |
| default_source = tmp_path / "candidates.jsonl" | |
| cache = tmp_path / "cache.parquet" | |
| monkeypatch.setattr(load_module, "DEFAULT_CANDIDATES", default_source) | |
| monkeypatch.setattr(load_module, "LOADED_CANDIDATES_CACHE", cache) | |
| _write_jsonl(default_source, [{"candidate_id": "CAND_0000001"}]) | |
| other_path = _write_jsonl(tmp_path / "custom.jsonl", [{"candidate_id": "CAND_OTHER"}]) | |
| load_candidates(other_path) # different path β cache untouched | |
| assert not cache.exists() | |
| load_candidates(default_source, limit=1) # limited read β cache untouched | |
| assert not cache.exists() | |
| def test_load_stale_cache_is_ignored(tmp_path: Path, monkeypatch) -> None: | |
| """A cache older than the source JSONL is treated as stale and a fresh parse runs instead.""" | |
| import os | |
| import preprocess.load as load_module | |
| source = tmp_path / "candidates.jsonl" | |
| cache = tmp_path / "cache.parquet" | |
| monkeypatch.setattr(load_module, "DEFAULT_CANDIDATES", source) | |
| monkeypatch.setattr(load_module, "LOADED_CANDIDATES_CACHE", cache) | |
| _write_jsonl(source, [{"candidate_id": "CAND_OLD"}]) | |
| load_candidates(source) # writes the cache reflecting CAND_OLD | |
| assert cache.exists() | |
| _write_jsonl(source, [{"candidate_id": "CAND_NEW"}]) # source content changes | |
| newer = cache.stat().st_mtime + 5 | |
| os.utime(source, (newer, newer)) # force the source's mtime strictly past the cache's | |
| refreshed = load_candidates(source) | |
| assert refreshed["candidate_id"].to_list() == ["CAND_NEW"] # stale cache ignored, live reparse happened | |