How Unit Tests in Tests/TestConversionEngine.mm Verify the Conversion Engine Logic

The unit tests in Tests/TestConversionEngine.mm validate every public method of the ConversionEngine class, ensuring correct data loading, MARISA Trie prefix search, frequency-based ranking, Phonex encoding, translation lookup, and spell-checking integration through hard-coded assertions against known dictionary entries.

The hallelujahim input method relies on the ConversionEngine class—implemented in src/ConversionEngine.mm—to power its predictive text, translation, and spell-checking features. The unit tests in Tests/TestConversionEngine.mm serve as the comprehensive validation suite, asserting that lexical data loads correctly from JSON sources and that search, ranking, and encoding algorithms return expected results for specific word queries like "test" and "courage".

Testing Data Loading and JSON Deserialization

The validation begins with ensuring the engine correctly deserializes its lexical database. The testWordsWithFrequencyAndTranslation method forces asynchronous data loading by accessing self.engine.wordsWithFrequencyAndTranslation and asserts that the JSON dictionary contains exactly 140,402 entries. It further validates that a known word entry, "test", contains the expected frequency value and translation array, confirming that loadPreparedData in src/ConversionEngine.mm (lines 27-36) correctly parses the dictionary/words_with_frequency_and_translation_and_ipa.json file using the internal deserializeJSON method.

Predictive search functionality is verified through testWordsStartsWith, which exercises the wordsStartsWith: method (lines 75-86 in src/ConversionEngine.mm). This test checks that a query for the prefix "test" returns exactly 95 candidates using the native C++ marisa::Trie implementation. The assertions confirm that the first results include expected words like "test" and "testing", validating that the trie structure correctly indexes the dictionary for fast prefix retrieval.

Verifying Frequency-Based Ranking

Two test methods ensure the sorting algorithm prioritizes common words. The testSortWordsByFrequency method confirms that after retrieving candidates, sortWordsByFrequency: (lines 89-103) reorders them by descending frequency, with the top-10 list matching expected high-frequency words. The testSortWordsByFrequencyFromLargeNumberOfCandidates test specifically validates behavior with large candidate sets—querying the prefix "in" returns over 50,000 words and asserts that the highest-frequency result is the word "in" itself, ensuring performance does not degrade with scale.

Testing Phonex Encoding via JavaScriptCore

Fuzzy phonetic matching is validated in testPhonexEncode, which exercises the phonexEncode: wrapper method (lines 107-108). The test verifies that the embedded phonex.js script, executed within a JSContext (lines 66-73), encodes words consistently. Specific assertions check that similar-sounding words like "courage" and "cerrage" map to the same Phonex code, and that "test" encodes to "T23", confirming the JavaScript-based phonetic algorithm integrates correctly with the Objective-C runtime.

Translation, IPA, and Annotation Accuracy

The test suite validates dictionary lookups and string construction through several focused tests.

testGetTranslations calls getTranslations: for the word "test" and validates the exact strings "n. 考验;试验;测试" and "vt. 试验;测试;接受测验" appear in the returned array from the lexical data.

testGetPhoneticSymbolOfWord asserts that getPhoneticSymbolOfWord: returns the correct IPA notation "tɛst" for the input "test".

testGetAnnotation and testGetAnnotationOfUpperCaseWord verify that getAnnotation: (lines 123-139) correctly concatenates IPA symbols and translation definitions into a multi-line formatted string, while also confirming case-insensitive processing preserves output accuracy.

Spell-Checking and Candidate Aggregation

Complex integration logic is tested through methods that combine multiple suggestion sources.

testGetSuggestionOfSpellChecker validates that getSuggestionOfSpellChecker: (lines 58-73) merges suggestions from macOS NSSpellChecker with Phonex-derived fuzzy matches. The test inputs misspellings like "aosome" and "Ausome", asserting the returned array contains expected corrections including phonetically similar words.

testGetCandidates exercises the most complex public method, getCandidates: (lines 82-122), which aggregates user-defined substitutions, MARISA Trie results, spell-checker suggestions, and entries from dictionary/cedict.json for pinyin support. The test confirms the method returns exactly 50 candidates (the enforced cap), deduplicates across sources, places the original input buffer at index 0, and correctly processes English prefixes ("tes"), phonetic approximations ("awsome"), and Chinese pinyin inputs ("xihongshi", "xhs").

testGetCandidatesWithUpperCaseInput specifically verifies that getCandidates: preserves original capitalization in the output list, ensuring the UI displays user-typed casing correctly.

Example Usage Patterns

The following Objective-C snippets demonstrate the same API surface validated by the unit tests in dongyuwei/hallelujahim.

// Obtain the singleton ConversionEngine
ConversionEngine *engine = [ConversionEngine sharedEngine];

// 1. Prefix search via MARISA Trie (fast predictive lookup)
NSArray *candidates = [engine wordsStartsWith:@"tes"];   // → ["test", "testing", …]

// 2. Frequency-based ranking
NSArray *sorted = [engine sortWordsByFrequency:candidates]; // Highest frequency first

// 3. Phonex encoding for fuzzy matching
NSString *code = [engine phonexEncode:@"courage"];   // → "K63"

// 4. Translation and IPA retrieval
NSArray *trans = [engine getTranslations:@"test"];
NSString *ipa  = [engine getPhoneticSymbolOfWord:@"test"];   // → "tɛst"

// 5. Full annotation construction (IPA + definitions)
NSString *annotation = [engine getAnnotation:@"test"];
// Returns: "[tɛst]\nn. 考验;试验;测试\nvt. 试验;测试;接受测验"

// 6. Spell-checking with phonetic fallback
NSArray *suggestions = [engine getSuggestionOfSpellChecker:@"aosome"];
// → ["Amos", "assume", "awesome", "assumes"]

// 7. Complete candidate aggregation (includes pinyin support)
NSArray *fullCandidates = [engine getCandidates:@"xihongshi"];
// Returns up to 50 unique suggestions including "tomato" and related terms

These patterns mirror the assertions in Tests/TestConversionEngine.mm, demonstrating how the engine supports live word completion, tooltip annotations, and multilingual input processing.

Summary

  • Data Loading: Tests verify 140,402 JSON entries load correctly via loadPreparedData in src/ConversionEngine.mm.
  • Prefix Search: MARISA Trie integration returns exact candidate counts (e.g., 95 results for "test") through wordsStartsWith:.
  • Frequency Ranking: sortWordsByFrequency: correctly orders 50,000+ candidates without performance degradation.
  • Phonetic Encoding: JavaScriptCore-based phonexEncode: generates consistent codes for fuzzy matching using the embedded phonex.js script.
  • Dictionary Lookups: Translation and IPA methods return exact strings for known entries like "test" from words_with_frequency_and_translation_and_ipa.json.
  • Integration: getCandidates: caps results at 50 items while merging spell-checker, trie, substitution, and pinyin sources from cedict.json.

Frequently Asked Questions

What specific conversion logic does TestConversionEngine.mm validate?

The file validates the entire ConversionEngine public API, including JSON data deserialization in loadPreparedData, MARISA Trie prefix searches via wordsStartsWith:, frequency sorting with sortWordsByFrequency:, Phonex encoding through phonexEncode:, and complex candidate aggregation in getCandidates:. Each test method targets a specific engine capability with hard-coded expected values derived from the dictionary files.

How do the tests verify the Phonex encoding algorithm?

The testPhonexEncode method checks that phonexEncode: returns consistent codes for phonetically similar words (e.g., "courage" and "cerrage" mapping to the same code) and validates specific outputs like "test" encoding to "T23". This confirms the embedded phonex.js script executes correctly within the JSContext initialized in src/ConversionEngine.mm (lines 66-73).

Why does the test suite check for exactly 50 candidates in getCandidates:?

The testGetCandidates method asserts the 50-item limit because getCandidates: (lines 82-122 in src/ConversionEngine.mm) intentionally caps results to ensure UI responsiveness. The test verifies this limit is enforced while confirming that deduplication occurs across the four input sources: user substitutions, MARISA Trie matches, spell-checker suggestions, and pinyin dictionary entries.

How does TestConversionEngine.mm handle case sensitivity testing?

The suite includes testGetAnnotationOfUpperCaseWord and testGetCandidatesWithUpperCaseInput to ensure getAnnotation: and getCandidates: process inputs case-insensitively while preserving the original capitalization in output strings. This validates that the engine normalizes search queries without destroying user-typed casing for display purposes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →