Skip to content

Improve testcoverage first iteration#246

Open
bmerkle wants to merge 8 commits intomicrosoft:mainfrom
bmerkle:improvetestcoverage
Open

Improve testcoverage first iteration#246
bmerkle wants to merge 8 commits intomicrosoft:mainfrom
bmerkle:improvetestcoverage

Conversation

@bmerkle
Copy link
Copy Markdown
Collaborator

@bmerkle bmerkle commented Apr 23, 2026

I generated some tests with GH Copilot to improve the testcoverage.

This PR:

  • contributes some test for modules which had no tests at all up to now
  • added some tests for already existing modules which had only low coverage

Overall we improved coverage from 72% to 80%. (report is below)
@KRRT7 can you please review the changes

 typeagent-py  coverage report
Name                                                Stmts   Miss Branch BrPart  Cover
-------------------------------------------------------------------------------------
src\typeagent\transcripts\transcript.py               158    117     54      0    19%
src\typeagent\emails\email_message.py                 101     60     38      0    29%
src\typeagent\knowpro\searchlang.py                   316    155    150     17    41%
src\typeagent\knowpro\messageutils.py                  35     17     18      1    47%
src\typeagent\mcp\server.py                           129     61     40      5    48%
src\typeagent\aitools\utils.py                        131     59     32      6    50%
src\typeagent\podcasts\podcast.py                     178     64     64     17    54%
src\typeagent\storage\memory\convthreads.py            39     16      8      3    55%
src\typeagent\knowpro\serialization.py                211     72    108     29    56%
src\typeagent\storage\sqlite\semrefindex.py            90     28     32      4    61%
src\typeagent\storage\memory\semrefindex.py           280     87    162     23    63%
src\typeagent\storage\sqlite\messageindex.py          170     48     58     16    66%
src\typeagent\knowpro\search.py                       241     61    104     25    68%
src\typeagent\knowpro\query.py                        493    125    174     20    69%
src\typeagent\knowpro\convutils.py                     17      5      6      2    70%
src\typeagent\knowpro\textlocindex.py                  65     17      6      2    70%
src\typeagent\knowpro\answers.py                      281     54    132     27    74%
src\typeagent\emails\email_import.py                  154     35     70      8    75%
src\typeagent\transcripts\transcript_ingest.py        137     21     64     14    78%
src\typeagent\storage\memory\messageindex.py           67     11     18      4    78%
src\typeagent\storage\memory\propindex.py             160     25     82     13    78%
src\typeagent\storage\sqlite\provider.py              279     53     78     11    79%
src\typeagent\knowpro\collections.py                  417     65    158     16    82%
src\typeagent\knowpro\conversation_base.py            136     13     56     16    83%
src\typeagent\storage\sqlite\propindex.py              66      7     14      6    84%
src\typeagent\storage\sqlite\schema.py                 82      9     14      4    84%
src\typeagent\knowpro\fuzzyindex.py                    37      5      2      1    85%
src\typeagent\podcasts\podcast_ingest.py               79      7     38      9    85%
src\typeagent\knowpro\convknowledge.py                 31      3      4      2    86%
src\typeagent\knowpro\dataclasses.py                   12      1      2      1    86%
src\typeagent\knowpro\factory.py                       19      2      2      1    86%
src\typeagent\storage\memory\provider.py               68      8      2      0    86%
src\typeagent\knowpro\secindex.py                      37      3      6      3    86%
src\typeagent\storage\utils.py                         11      1      4      1    87%
src\typeagent\aitools\model_adapters.py               151     12     42      9    89%
src\typeagent\storage\memory\reltermsindex.py         157      9     64     14    90%
src\typeagent\knowpro\field_helpers.py                 30      2     10      2    90%
src\typeagent\knowpro\utils.py                          9      1      2      0    91%
src\typeagent\aitools\vectorbase.py                   149     11     62      8    91%
src\typeagent\knowpro\interfaces_core.py              162     10     18      2    91%
src\typeagent\storage\sqlite\collections.py           185      9     48     11    91%
src\typeagent\knowpro\interfaces_storage.py            46      2      2      0    92%
src\typeagent\storage\memory\timestampindex.py         64      3     20      4    92%
src\typeagent\storage\sqlite\reltermsindex.py         173      8     52      7    92%
src\typeagent\knowpro\universal_message.py             64      3     10      2    93%
src\typeagent\aitools\auth.py                          30      1      6      1    94%
src\typeagent\knowpro\convsettings.py                  44      1      4      1    96%
src\typeagent\knowpro\knowledge.py                     79      2     30      2    96%
src\typeagent\knowpro\searchlib.py                     85      2     38      0    98%
src\typeagent\__init__.py                               2      0      0      0   100%
src\typeagent\aitools\embeddings.py                    47      0      8      0   100%
src\typeagent\knowpro\answer_context_schema.py         22      0      0      0   100%
src\typeagent\knowpro\answer_response_schema.py         9      0      0      0   100%
src\typeagent\knowpro\common.py                         3      0      0      0   100%
src\typeagent\knowpro\date_time_schema.py              21      0      0      0   100%
src\typeagent\knowpro\interfaces.py                    12      0      0      0   100%
src\typeagent\knowpro\interfaces_indexes.py            42      0      0      0   100%
src\typeagent\knowpro\interfaces_search.py             36      0      0      0   100%
src\typeagent\knowpro\interfaces_serialization.py      51      0      0      0   100%
src\typeagent\knowpro\knowledge_schema.py              52      0      0      0   100%
src\typeagent\knowpro\search_query_schema.py           39      0      0      0   100%
src\typeagent\storage\__init__.py                       3      0      0      0   100%
src\typeagent\storage\memory\__init__.py                3      0      0      0   100%
src\typeagent\storage\memory\collections.py            32      0      4      0   100%
src\typeagent\storage\sqlite\__init__.py                9      0      0      0   100%
src\typeagent\storage\sqlite\timestampindex.py         46      0     10      0   100%
-------------------------------------------------------------------------------------
TOTAL                                                6584   1391   2230    370    73%
Name                                                Stmts   Miss Branch BrPart  Cover
-------------------------------------------------------------------------------------
src\typeagent\podcasts\podcast.py                     178     64     64     17    54%
src\typeagent\mcp\server.py                           129     52     40      5    56%
src\typeagent\storage\sqlite\semrefindex.py            90     28     32      4    61%
src\typeagent\storage\memory\semrefindex.py           280     86    162     22    63%
src\typeagent\storage\sqlite\messageindex.py          170     48     58     16    66%
src\typeagent\knowpro\serialization.py                211     47    108     31    69%
src\typeagent\knowpro\query.py                        493    118    174     21    70%
src\typeagent\knowpro\search.py                       241     52    104     26    72%
src\typeagent\emails\email_import.py                  154     35     70      8    75%
src\typeagent\transcripts\transcript_ingest.py        137     21     64     14    78%
src\typeagent\storage\memory\messageindex.py           67     11     18      4    78%
src\typeagent\storage\memory\propindex.py             160     25     82     13    78%
src\typeagent\knowpro\answers.py                      281     45    132     30    78%
src\typeagent\storage\sqlite\provider.py              279     53     78     11    79%
src\typeagent\knowpro\collections.py                  417     65    158     16    82%
src\typeagent\knowpro\conversation_base.py            136     13     56     16    83%
src\typeagent\knowpro\searchlang.py                   316     39    150     27    83%
src\typeagent\storage\sqlite\propindex.py              66      7     14      6    84%
src\typeagent\storage\sqlite\schema.py                 82      9     14      4    84%
src\typeagent\knowpro\fuzzyindex.py                    37      5      2      1    85%
src\typeagent\podcasts\podcast_ingest.py               79      7     38      9    85%
src\typeagent\aitools\utils.py                        131     18     32      4    85%
src\typeagent\transcripts\transcript.py               158     11     54     18    85%
src\typeagent\knowpro\convknowledge.py                 31      3      4      2    86%
src\typeagent\knowpro\dataclasses.py                   12      1      2      1    86%
src\typeagent\knowpro\factory.py                       19      2      2      1    86%
src\typeagent\storage\memory\provider.py               68      8      2      0    86%
src\typeagent\knowpro\secindex.py                      37      3      6      3    86%
src\typeagent\storage\utils.py                         11      1      4      1    87%
src\typeagent\knowpro\textlocindex.py                  65      8      6      0    89%
src\typeagent\aitools\model_adapters.py               151     12     42      9    89%
src\typeagent\knowpro\field_helpers.py                 30      2     10      2    90%
src\typeagent\storage\memory\reltermsindex.py         157      8     64     14    90%
src\typeagent\knowpro\utils.py                          9      1      2      0    91%
src\typeagent\knowpro\interfaces_core.py              162     10     18      2    91%
src\typeagent\storage\sqlite\collections.py           185      9     48     11    91%
src\typeagent\knowpro\interfaces_storage.py            46      2      2      0    92%
src\typeagent\storage\memory\timestampindex.py         64      3     20      4    92%
src\typeagent\aitools\vectorbase.py                   149     10     62      7    92%
src\typeagent\storage\sqlite\reltermsindex.py         173      8     52      7    92%
src\typeagent\knowpro\messageutils.py                  35      2     18      2    92%
src\typeagent\knowpro\universal_message.py             64      3     10      2    93%
src\typeagent\emails\email_message.py                 101      2     38      6    94%
src\typeagent\aitools\auth.py                          30      1      6      1    94%
src\typeagent\knowpro\convsettings.py                  44      1      4      1    96%
src\typeagent\knowpro\knowledge.py                     79      2     30      2    96%
src\typeagent\storage\memory\convthreads.py            39      0      8      1    98%
src\typeagent\knowpro\searchlib.py                     85      2     38      0    98%
src\typeagent\__init__.py                               2      0      0      0   100%
src\typeagent\aitools\embeddings.py                    47      0      8      0   100%
src\typeagent\knowpro\answer_context_schema.py         22      0      0      0   100%
src\typeagent\knowpro\answer_response_schema.py         9      0      0      0   100%
src\typeagent\knowpro\common.py                         3      0      0      0   100%
src\typeagent\knowpro\convutils.py                     17      0      6      0   100%
src\typeagent\knowpro\date_time_schema.py              21      0      0      0   100%
src\typeagent\knowpro\interfaces.py                    12      0      0      0   100%
src\typeagent\knowpro\interfaces_indexes.py            42      0      0      0   100%
src\typeagent\knowpro\interfaces_search.py             36      0      0      0   100%
src\typeagent\knowpro\interfaces_serialization.py      51      0      0      0   100%
src\typeagent\knowpro\knowledge_schema.py              52      0      0      0   100%
src\typeagent\knowpro\search_query_schema.py           39      0      0      0   100%
src\typeagent\storage\__init__.py                       3      0      0      0   100%
src\typeagent\storage\memory\__init__.py                3      0      0      0   100%
src\typeagent\storage\memory\collections.py            32      0      4      0   100%
src\typeagent\storage\sqlite\__init__.py                9      0      0      0   100%
src\typeagent\storage\sqlite\timestampindex.py         46      0     10      0   100%
-------------------------------------------------------------------------------------
TOTAL                                                6584    963   2230    402    80%

Copilot AI review requested due to automatic review settings April 23, 2026 17:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR focuses on increasing unit test coverage across the typeagent Python package and improving local coverage workflows (notably on Windows) so coverage reporting targets the actual library code under src/typeagent.

Changes:

  • Added multiple new unit test modules covering previously-untested (or low-coverage) areas (e.g., search language compilation, serialization, transcripts, memory indexes).
  • Updated Windows make.bat to add a coverage target and run coverage via uv.
  • Updated .coveragerc to measure coverage for the typeagent package instead of tests.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tests/test_utils.py Adds additional unit tests for utility helpers and client creation paths.
tests/test_transcripts.py Extends transcript tests (speaker parsing, serialize/deserialize, file round-trips, alias building).
tests/test_textlocindex.py New tests for TextToTextLocationIndex (empty/clear/serialize/deserialize/get).
tests/test_serialization.py Adds more serialization/deserialization edge-case tests and knowledge deserialization tests.
tests/test_searchlang_compile.py New unit tests for searchlang.py compile paths that don’t require a live LLM.
tests/test_search.py New tests for SearchOptions, ConversationSearchResult, and non-searchable paths.
tests/test_messageutils.py New tests for chunk batching and text range helper logic.
tests/test_memory_semrefindex.py New tests for memory semantic ref index helper functions.
tests/test_mcp_server.py Adds more unit coverage for MCP server model response formats, repr, and argument validation.
tests/test_email_message.py New tests for email message metadata parsing, knowledge extraction, and serialization.
tests/test_convutils.py New tests for conversation time range helpers and prompt section generation.
tests/test_convthreads.py New tests for in-memory conversation thread storage/indexing behavior.
make.bat Adds coverage command for Windows developer workflow.
.coveragerc Adjusts coverage source to typeagent so reports reflect library coverage.

Comment thread tests/test_serialization.py Outdated
Comment thread tests/test_serialization.py
Comment thread tests/test_mcp_server.py
Comment thread tests/test_utils.py Outdated
Comment thread tests/test_serialization.py Outdated
Comment thread tests/test_serialization.py Outdated
Comment thread tests/test_serialization.py Outdated
Comment thread tests/test_mcp_server.py
Comment thread tests/test_searchlang_compile.py Outdated
Comment thread tests/test_serialization.py Outdated
@gvanrossum
Copy link
Copy Markdown
Collaborator

Can you turn the changes to .coveragerc and make.bat into a separate PR? Those are in theory uncontroversial, although for me, the source should be 'src', not 'typeagent'.

Copy link
Copy Markdown
Contributor

@KRRT7 KRRT7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up — good to see tests for modules that previously had zero coverage. The .coveragerc fix (source = testsource = typeagent) is correct, I had the same note in #242.

A few things to address before this can merge:

Merge conflict

PR #244 (merged earlier today) also modified tests/test_utils.py — added TestResolveAzureModelName and some formatting changes. You'll need to rebase onto current main.

AGENTS.md violations

The Copilot-generated tests tripped a few repo conventions (AGENTS.md):

  1. Imports inside test functions — Several new tests in test_serialization.py, test_utils.py, and others have local imports (from typeagent.knowpro.serialization import ... etc). AGENTS.md requires top-level imports unless it's __main__/main(), pydantic/logfire, or circular import avoidance. These should be hoisted to the module import section.

  2. MagicMock usage (test_mcp_server.py) — AGENTS.md says "don't mock; use the regular implementation (maybe introduce a fixture to create it)". For something like a __repr__ test, simple sentinel objects (object() or SimpleNamespace) work fine without mock-spec concerns.

  3. ConversationSettings() without test embedding model (test_mcp_server.py) — The default constructor calls create_embedding_model() which can require real API keys. Tests that need a ConversationSettings should pass create_test_embedding_model() so they stay offline/CI-safe.

  4. Vacuous assertion (test_searchlang_compile.py) — assert len(group.terms) >= 0 is always true for any list. This should assert the actual expected outcome for the both-wildcards facet case.

Context on scope

Heads up — Guido closed #242 and indicated he'd rather test coverage not become an explicit project focus right now. That said, the .coveragerc fix and tests for previously-untested modules (convthreads, convutils, email_message, messageutils, textlocindex) stand on their own as gap-filling. Might be worth reframing the PR description to emphasize those targeted additions rather than coverage numbers.

Copy link
Copy Markdown
Contributor

@KRRT7 KRRT7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran the full test suite locally — 21 failures and 1 collection error. Most are because the fork is out of sync with main (PRs #235, #241, #244 landed after your branch diverged). A rebase will fix those. But there are also some genuine test bugs and AGENTS.md issues worth fixing in the same pass.

After rebase: 15 of 21 failures will resolve themselves

These are stale-fork issues, not test bugs:

  • test_mcp_server.py — imports resolve_azure_model_name which was added in #244
  • test_utils.py pretty_print/format_code tests#235 replaced black with pprint, output is now double-quoted
  • test_utils.py parse_azure_endpoint tests#241 changed endpoint parsing behavior
  • test_utils.py — calls parse_azure_endpoint_parts and resolve_azure_model_name, both added in #244

Genuine test bugs (won't fix on rebase)

test_memory_semrefindex.py — 5 TypeError failures. Every add_entity/add_topic/add_action call is missing the required chunk_ordinal positional argument. These have never worked. See inline comment.

test_transcripts.pytest_transcript_knowledge_extraction_slow hits a real LLM API and fails without keys.

AGENTS.md issues across the new files

  • Imports from re-export barrel — 7 files import from typeagent.knowpro.interfaces instead of the defining module (interfaces_core, interfaces_search, interfaces_serialization). AGENTS.md: "Never import from a module that just re-exports it."
  • Local imports inside test functionstest_convthreads.py (line 87), test_search.py (line 84). AGENTS.md: "Don't put imports inside functions."
  • MagicMock usage in test_mcp_server.py — AGENTS.md: "don't mock; use the regular implementation."
  • ConversationSettings() without test embedding model in test_mcp_server.py — default constructor calls create_embedding_model() which needs real API config.

Weak assertions worth tightening

Several passing tests have assertions that can never fail:

  • test_searchlang_compile.py: assert len(group.terms) >= 0 — always true for any list
  • test_convthreads.py: test_lookup_thread_returns_matches only asserts isinstance(results, list) — never checks the results are non-empty or correct
  • test_search.py: test_search_options_defaults and test_conversation_search_result_basic just reconstruct constructor args
  • test_memory_semrefindex.py: test_add_term_empty_string_is_stored only checks size() == 1, never verifies the stored term
  • test_utils.py: test_uppercase_identity_not_plain name/comment claim "IDENTITY" is NOT routed to the identity provider, but the code does .lower() so it IS — the test actually passes "APIKEY123" and tests the same path as test_plain_key_returned_as_is

Comment thread tests/test_memory_semrefindex.py
Comment thread tests/test_searchlang_compile.py
Comment thread tests/test_search.py
Comment thread tests/test_convthreads.py
Comment thread tests/test_convthreads.py
@gvanrossum
Copy link
Copy Markdown
Collaborator

Odd about the .coverage changes. With source=typeagent, on Linux (WSL), I got "no reports". Setting it to src gave the expected report. Would your please try with src?

@bmerkle
Copy link
Copy Markdown
Collaborator Author

bmerkle commented Apr 24, 2026

Can you turn the changes to .coveragerc and make.bat into a separate PR? Those are in theory uncontroversial, although for me, the source should be 'src', not 'typeagent'.

moved to #249

bmerkle and others added 7 commits April 24, 2026 20:50
for existing modules:
- updated import statements
- added additional test functions
- added new test modules for modules with missing tests cases
Co-authored-by: Copilot <copilot@github.com>
- added new test modules for modules with missing tests cases
Co-authored-by: Copilot <copilot@github.com>
@bmerkle bmerkle force-pushed the improvetestcoverage branch from 3a0009a to 58a40f8 Compare April 24, 2026 18:55
Removed duplicate import statements for AsyncAzureOpenAI and AsyncOpenAI.
@bmerkle bmerkle requested a review from KRRT7 April 24, 2026 19:02
@bmerkle
Copy link
Copy Markdown
Collaborator Author

bmerkle commented Apr 24, 2026

@KRRT7 can you please check again ? should have addressed all you comments

Copy link
Copy Markdown
Contributor

@KRRT7 KRRT7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All review feedback addressed. Thanks for the quick turnaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants