Adrienne Vermorel
Workflows avancés avec Claude Code : tests, documentation et débogage pour les analytics engineers
Vous utilisez Claude Code pour les tâches de base. Écrire du SQL, créer des modèles, peut-être générer du code répétitif. Ça fonctionne, mais votre workflow reste manuel. Vous promptez une chose à la fois, vérifiez le résultat, promptez à nouveau. L’outil aide, mais il n’a pas fondamentalement changé votre façon de travailler.
La plupart des tutoriels s’arrêtent à « demandez à Claude d’écrire du code » sans couvrir les workflows systématiques et répétables. Cet article en présente trois : tests, documentation et débogage. Chacun transforme Claude Code de quelque chose à qui vous parlez en quelque chose d’intégré à votre processus.
Je suppose que vous êtes déjà à l’aise avec les bases de Claude Code et que vous travaillez avec dbt sur BigQuery. Si vous débutez avec Claude Code, commencez plutôt par mon guide de première heure.
Fondation : configurer Claude Code pour les projets dbt
Avant de construire des workflows, vous avez besoin des bonnes bases. Ça commence avec CLAUDE.md.
CLAUDE.md comme mémoire de projet
CLAUDE.md est un fichier que Claude charge automatiquement en contexte au début d’une conversation. Il élimine le besoin de répéter les décisions d’architecture, les exigences de test et les conventions de code à chaque session. Créez-le à la racine de votre projet et Claude le lit automatiquement.
La clé est de rester concis. Les LLM de pointe peuvent suivre de manière fiable environ 150-200 instructions. Le prompt système de Claude Code en contient déjà environ 50, ce qui laisse une capacité limitée pour vos instructions personnalisées. N’entassez pas toutes les commandes possibles dans CLAUDE.md. Incluez ce qui est universellement applicable, référencez des fichiers séparés pour la documentation détaillée, et utilisez des pointeurs au lieu de copier des extraits de code (ils deviennent vite obsolètes).
Voici un template qui fonctionne pour les projets dbt/BigQuery :
# Project Overview
## What- Analytics engineering project using dbt Core with BigQuery- Marketing attribution data transformations- GA4 BigQuery exports processing
## Key Commands- `dbt run --select model_name` - Run single model- `dbt run --select +model_name` - Run with upstream dependencies- `dbt test --select model_name` - Test single model- `dbt build --select model_name` - Run + test in DAG order
## Project Structuremodels/├── base/ # Source-conformed, atomic building blocks├── intermediate/ # Purpose-built transformations└── marts/ # Business-conformed, end-user ready
## Naming Conventions- Base: `base__{source}__{table}`- Intermediate: `int__{entity}_{verb}`
## Code Standards- Use CTEs for readability- Always use ref() or source()- Add unique + not_null tests to primary keys- Document all models in schema.ymlClaude lit les fichiers CLAUDE.md depuis plusieurs emplacements : un global à ~/.claude/CLAUDE.md, la racine du projet, un personnel CLAUDE.local.md (gitignored), et les répertoires enfants à la demande pour les monorepos. Lancez /init pour auto-générer un fichier de départ, puis affinez-le en fonction de ce que Claude fait mal. Pour approfondir la configuration de CLAUDE.md, consultez mon guide complet sur la configuration de CLAUDE.md pour les projets dbt.
Les hooks pour des garde-fous déterministes
Les hooks sont des commandes shell qui s’exécutent à des moments spécifiques du cycle de vie de Claude Code. Ils fournissent un contrôle déterministe sur le comportement de Claude, garantissant que certaines actions se produisent toujours, quel que soit votre prompt.
Pour les workflows dbt, les hooks les plus utiles sont PostToolUse (s’exécute après que Claude a terminé un outil) et PreToolUse (s’exécute avant l’exécution). Vous pouvez auto-formater le SQL après les éditions, bloquer les modifications sur les schémas de production, ou lancer automatiquement dbt compile après les changements de modèle.
Voici un hook qui lance sqlfluff après toute édition SQL :
{ "hooks": { "PostToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "jq -r '.tool_input.file_path' | { read f; if echo \"$f\" | grep -q '\\.sql$'; then sqlfluff fix \"$f\" --dialect bigquery; fi; }" } ] } ] }}Et un qui bloque les modifications sur les fichiers mart de production :
{ "hooks": { "PreToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "python3 -c \"import json, sys; d=json.load(sys.stdin); p=d.get('tool_input',{}).get('file_path',''); sys.exit(2 if 'models/marts/prod/' in p else 0)\"" } ] } ] }}Le code de sortie 0 signifie que le hook passe. Le code 2 bloque l’action et affiche l’erreur à Claude. Les autres codes non-zéro loguent l’erreur mais continuent. Je couvre les hooks et les commandes personnalisées plus en détail dans un article séparé si vous voulez approfondir.
Workflows de test
Le développement piloté par les tests avec Claude Code
Le TDD fonctionne particulièrement bien avec les agents IA. Vous donnez à Claude une cible claire (des tests qui passent), il itère jusqu’à y arriver, et vous avez la certitude que le résultat fonctionne réellement. Le workflow comporte cinq étapes.
D’abord, écrivez les tests avant que le modèle existe :
Write dbt tests for a new mrt__marketing__customer_lifetime_value model. Include:- unique + not_null on customer_id- accepted_values for customer_segment- relationships test to base__stripe__customersDon't create the model yet.Puis confirmez que les tests échouent :
Run dbt test --select mrt__marketing__customer_lifetime_value and confirm all tests fail.Maintenant, implémentez pour que ça passe :
Implement mrt__marketing__customer_lifetime_value to make all tests pass.Don't modify the tests.Si quelque chose échoue, itérez :
The relationship test is failing. Fix the implementation without changing the test.Une fois les tests passés, refactorisez en confiance :
Now that tests pass, refactor the CTEs for better readability while keeping all tests green.Cette approche détecte les problèmes tôt. Claude sait exactement à quoi ressemble le résultat attendu, et vous savez que le résultat fonctionne vraiment.
Générer des tests dbt automatiquement
Vous pouvez créer une commande slash qui analyse un modèle et génère les tests appropriés. Enregistrez ceci dans .claude/commands/generate-tests.md :
---description: Generate comprehensive dbt tests for a modelallowed-tools: Read, Write, Bash(dbt:*)argument-hint: [model_name]---Analyze $ARGUMENTS and generate appropriate tests:
1. Read the model SQL and existing schema.yml2. Identify primary key columns → add unique + not_null3. Find foreign key relationships → add relationships tests4. Detect enum-like columns → add accepted_values5. Find numeric ranges → add appropriate range tests
Update the schema.yml with new tests.Tapez /generate-tests mrt__sales__orders et Claude analyse le modèle, identifie ce qui devrait être testé, et met à jour votre schema.yml. Ce n’est pas parfait, mais ça attrape les évidences et vous donne un point de départ.
Imposer la discipline de test
Claude saute parfois les tests ou écrit l’implémentation en premier. Vous pouvez utiliser des hooks pour imposer la discipline TDD en interceptant les modifications de fichiers et en validant contre les violations courantes : implémenter une fonctionnalité sans test qui échoue, écrire plusieurs tests avant toute implémentation, ou modifier les tests pour les faire passer.
Le pattern est de créer un hook PreToolUse qui vérifie si le changement suit vos attentes de test. Sinon, il bloque et dit à Claude pourquoi.
Pour valider les prompts avant de les utiliser sur du code de production, créez une commande /test-prompt qui lance d’abord votre prompt sur un modèle sandbox, vérifie que la sortie a une syntaxe BigQuery correcte et utilise correctement ref() et source(), et documente les cas limites. Testez sur des modèles hors production avant de lancer quelque chose sur tout votre projet.
Workflows de documentation
Le problème de la documentation
Écrire des descriptions pour plus de 100 modèles et colonnes est fastidieux. Les fichiers schema.yml finissent incohérents entre les membres de l’équipe, et la documentation dérive de la réalité au fur et à mesure que les modèles changent. Vous savez que vous devriez tout documenter, mais ce travail manuel n’est jamais priorisé.
Le pattern en deux étapes
La solution combine dbt codegen avec Claude Code. D’abord, générez la structure du schéma avec codegen :
dbt run-operation generate_model_yaml --args '{"model_names": ["base__ga4__events"], "upstream_descriptions": true}'Cela vous donne la structure YAML avec tous les noms de colonnes. Puis utilisez Claude Code pour remplir les descriptions :
Read the base__ga4__events.sql model and the generated schema.yml scaffold.For each column:1. Analyze the SQL transformation logic2. Infer the business meaning3. Write a clear, concise description4. Add appropriate tests
Follow these standards:- Use present tense- Include data type in description- Note any known limitationsClaude lit le SQL, comprend ce que fait chaque colonne, et écrit des descriptions qui reflètent vraiment les transformations. Ce n’est pas parfait (relisez avant de commiter), mais c’est plus rapide que tout écrire manuellement.
Une commande slash pour la documentation de modèle
Enregistrez ceci dans .claude/commands/document-model.md :
---description: Generate comprehensive dbt documentation for a modelallowed-tools: Bash(dbt:*), Read, Writeargument-hint: [model_name]---# Document Model: $ARGUMENTS
1. Read the model SQL file at models/**/$ARGUMENTS.sql2. Identify all columns and their transformations3. Check if schema.yml exists for this model4. Generate or update the schema.yml with: - Model description explaining business purpose - Column descriptions explaining meaning and source - Appropriate tests for each column
## Documentation Standards- Model descriptions: Start with "This model..." and explain the grain- Column descriptions: Include data type, business meaning, and source- Use consistent terminology from our data dictionary
Create/update the schema.yml file and show a summary of changes.Tapez /document-model int__ga4__sessions_sessionized et vous obtenez la documentation en une seule commande.
Les docs blocks pour la cohérence
Les mêmes colonnes apparaissent dans plusieurs modèles. customer_id est partout, et vous vous retrouvez avec des descriptions légèrement différentes à chaque fois. La solution, ce sont les docs blocks de dbt.
Créez un fichier models/docs.md avec de la documentation réutilisable :
{% docs customer_id %}Unique identifier for a customer account.Format: UUID generated at account creation.Source: Stripe customer API.{% enddocs %}
{% docs event_timestamp %}Timestamp when the event was recorded in UTC.Microsecond precision from GA4 BigQuery export.{% enddocs %}Puis référencez-les dans votre schema.yml :
columns: - name: customer_id description: "{{ doc('customer_id') }}"Vous pouvez demander à Claude d’analyser tous vos modèles, identifier les colonnes communément répétées, créer un fichier docs.md avec des blocs réutilisables, et mettre à jour les fichiers schema.yml pour les référencer. Même colonne, même description, partout.
Documentation de la lignée
Claude peut générer des diagrammes Mermaid montrant la lignée des données :
Create a Mermaid flowchart showing the lineage from raw GA4 eventsto the final marketing attribution model. Include all intermediatetransformations and key business logic at each step.Le résultat ressemble à :
flowchart TD A[raw.ga4_events] --> B[base__ga4__events] B --> C[int__ga4_sessions_sessionized] C --> D[int__ga4_sessions_attributed] D --> E[mrt__marketing__attributed_conversions]Utile pour l’onboarding de nouveaux membres d’équipe ou pour documenter des chaînes de transformation complexes.
Workflows de débogage
Laissez Claude Code affronter les erreurs
La meilleure approche de débogage est simple : laissez Claude Code exécuter le modèle et se confronter directement aux erreurs. Ne pré-collectez pas les preuves et n’inspectez pas manuellement les logs. Dites simplement à Claude ce que vous essayez d’accomplir et laissez-le itérer.
Run dbt build --select mrt__sales__orders and fix any errors.Claude exécutera la commande, verra la sortie d’erreur, vérifiera le SQL compilé si nécessaire, et proposera des corrections. Il itère jusqu’à ce que le modèle s’exécute avec succès. Ça fonctionne parce que Claude Code peut exécuter des commandes, lire des fichiers et faire des modifications dans une seule boucle de conversation.
Pour les problèmes de données où le modèle s’exécute mais produit de mauvais résultats :
The mrt__sales__orders model shows incorrect total_revenue for customer_id='ABC123'.Trace through the upstream models to find where the calculation goes wrong.Claude lira le modèle, identifiera les dépendances, interrogera les tables intermédiaires, et trouvera où les valeurs divergent. Vous n’avez pas besoin de lui dire comment déboguer. Décrivez simplement le problème et laissez-le investiguer.
Les subagents pour le débogage complexe
Pour les problèmes particulièrement épineux, vous pouvez créer un subagent dédié au débogage. Enregistrez ceci dans .claude/agents/sql-debugger.md :
---name: sql-debuggerdescription: Specialized agent for debugging SQL and dbt issues---
You are an expert SQL debugger specializing in BigQuery and dbt.
## Your Approach
1. **Gather Evidence First** - Read error logs completely - Check compiled SQL - Review recent git changes to the model
2. **Form Hypotheses** - List possible causes ranked by likelihood - Consider: data issues, schema changes, logic errors
3. **Test Systematically** - Isolate the problem with minimal reproducing case - Use WHERE clauses to test on small data - Add CTEs to inspect intermediate results
4. **Fix and Verify** - Implement the minimum change to fix the issue - Add tests to prevent regression - Document the root causeInvoquez-le avec :
Use the sql-debugger agent to investigate why int__ga4__sessions_attributedis returning NULL for channel_grouping on 5% of sessions.Le subagent obtient un contexte frais entièrement focalisé sur le débogage. Utile quand votre conversation principale est encombrée d’autre contexte.
Assembler le tout
Ces workflows se connectent naturellement. Vous recevez une demande pour un nouveau modèle, utilisez /generate-tests pour écrire les tests d’abord, implémentez le modèle avec Claude qui itère jusqu’à ce que les tests passent, dites à Claude de corriger les erreurs qui surviennent, lancez /document-model avant d’ouvrir une PR, et commitez avec une couverture de test complète et de la documentation.
La valeur n’est pas dans une seule commande. Elle est dans les patterns systématiques et répétables. Claude Code devient partie intégrante de votre processus plutôt que quelque chose à qui vous posez occasionnellement des questions.
Partagez tout ça avec votre équipe en commitant CLAUDE.md et votre dossier de commandes dans git. Tout le monde obtient les mêmes workflows, les mêmes garde-fous, les mêmes standards de documentation.
Commencez par un seul workflow. /document-model est probablement le point d’entrée le plus facile puisque la documentation est toujours en retard et que la commande apporte une valeur immédiate. Une fois que ça fonctionne, ajoutez les workflows de test. Construisez progressivement.
L’objectif n’est pas de tout automatiser. C’est d’automatiser les parties fastidieuses pour que vous puissiez vous concentrer sur les décisions qui comptent vraiment.