Skip to content

[Tests] Add unit tests for ClaudeCodeReader (claude_code_reader.py) #2

@ngmks

Description

@ngmks

🏷️ Priorité : HAUTE | Type : Tests manquants

Contexte

Le fichier apps/claude_code_data/claude_code_reader.py (385 lignes) est le cœur de l'ingestion des sessions Claude Code dans LEANN. Il lit les fichiers JSONL, découvre les projets, groupe les entrées en "turns" (user + assistant), extrait les metadata et construit les documents pour l'indexation.

Actuellement : ZÉRO test. C'est le module le plus critique du fork et il n'a aucune couverture.

Fichiers concernés

  • Module à tester : apps/claude_code_data/claude_code_reader.py
  • Fichier test à créer : tests/test_claude_code_reader.py
  • Référence pattern : tests/test_multi_language_ast.py (pour le style de test du projet)

Architecture du module

Le ClaudeCodeReader hérite de llama_index.core.readers.base.BaseReader et expose ces méthodes :

Méthode Lignes Rôle
load_data(input_dir, **kwargs) 51-147 Point d'entrée principal
_discover_projects(base_dirs) 153-174 Scanne les répertoires pour trouver les projets
_extract_project_name(project_dir) 176-200 Décode le nom de projet à partir du chemin encodé
_read_jsonl(file_path) 206-222 Parsing JSONL ligne par ligne avec gestion d'erreur
_build_turn_docs(entries, session_id, ...) 228-330 Groupe les entrées en turns user/assistant
_extract_text_content(content) 336-355 Extrait le texte d'un champ content (string ou array)
_extract_assistant_content(content) 357-384 Extrait contenu assistant, noms d'outils, skip thinking blocks

Tests à écrire (~20 tests)

1. Découverte de projets

class TestProjectDiscovery:
    def test_discover_finds_valid_projects():
        # Créer tmpdir avec structure ~/.claude/projects/<hash>/*.jsonl
        # Vérifier que le projet est trouvé
    
    def test_discover_skips_dirs_without_jsonl():
        # Répertoire sans .jsonl → pas retourné
    
    def test_discover_handles_missing_base_dir():
        # base_dir inexistant → liste vide, pas de crash
    
    def test_discover_multiple_base_dirs():
        # Plusieurs base_dirs → tous scannés

2. Extraction du nom de projet

class TestProjectNameExtraction:
    def test_extract_standard_path():
        # '-home-mks-projects-leann-fork' → 'leann-fork'
    
    def test_extract_single_segment():
        # '-my-project' → 'my-project'
    
    def test_extract_edge_case_empty():
        # Chemin vide → ne crashe pas

3. Parsing JSONL

class TestJSONLParsing:
    def test_read_valid_lines()
    def test_read_skips_malformed_lines()
    def test_read_empty_file()
    def test_read_unicode_content()
    def test_read_missing_file()

4. Construction des turns

class TestTurnBuilding:
    def test_pairs_user_assistant()
    def test_metadata_fields_present()  # session_id, project_name, turn_id
    def test_extracts_tool_names()
    def test_skips_thinking_blocks()
    def test_formats_header()
    def test_handles_missing_fields()

5. Intégration

class TestIntegration:
    def test_load_data_end_to_end()
    def test_load_data_respects_max_count()
    def test_load_data_respects_project_filter()
    def test_load_data_includes_subagent_files()

Fixtures nécessaires

Créer tests/fixtures/claude_code_sessions/ avec :

  • Un fichier JSONL valide (5-10 entrées user/assistant alternées)
  • Un fichier JSONL avec lignes malformées
  • Un fichier JSONL vide
  • Un fichier JSONL avec contenu unicode/emoji

Critères de succès

  • pytest tests/test_claude_code_reader.py passe à 100%
  • Couverture des 7 méthodes
  • Aucune dépendance externe (tmpdir + fixtures locales)
  • Tests isolés (pas de side effects entre tests)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions