| name | create-codeql-query-tdd-generic |
|---|---|
| description | Develop CodeQL tool queries using test-driven development with the CodeQL Development MCP Server. Use this when creating new CodeQL queries or enhancing existing ones for any supported language (actions, cpp, csharp, go, java, javascript, python, ruby, swift). |
This skill guides you through developing CodeQL tool queries using test-driven development (TDD) with the CodeQL Development MCP Server tools.
You are developing CodeQL queries organized in query packs:
- Query packs: Typically
<query-pack>/src/- Contains tool query implementations - Test packs: Typically
<query-pack>/test/- Contains test cases and expected results - Supported languages: actions, cpp, csharp, go, java, javascript, python, ruby, swift
Adapt the directory structure to match your project's query pack organization.
Before writing any code:
-
Understand the Query Purpose
- What should this tool query detect or analyze?
- What inputs does it need?
- What outputs should it produce?
-
Define Test Scenarios
- Positive cases: Code that should match
- Negative cases: Code that should not match
- Edge cases: Boundary conditions
For a new query named {QueryName} for language {language}:
-
Create test directory within your query pack:
<query-pack>/test/{QueryName}/ -
Create test source code (
test.{ext}):- Include positive test cases (code that should be detected)
- Include negative test cases (code that should NOT be detected)
- Include edge cases (unusual but valid scenarios)
- Add comments explaining what each section tests
-
Create expected results file (
{QueryName}.expected):| file | line | col | endLine | endCol | message | | test.js | 2 | 1 | 4 | 2 | Function: myFunc | -
Create test reference file (
{QueryName}.qlref):src/{QueryName}/{QueryName}.ql(Path relative to the query pack directory)
Use the codeql_test_extract tool:
{
"testPath": "<query-pack>/test/{QueryName}",
"searchPath": ["<query-pack>"]
}This creates a test database at <query-pack>/test/{QueryName}/{QueryName}.testproj/.
Before implementing the query, understand the AST structure of your test code:
-
Run PrintAST query using
codeql_query_run(if available in your query pack):{ "queryPath": "<query-pack>/src/PrintAST/PrintAST.ql", "database": "<query-pack>/test/{QueryName}/{QueryName}.testproj", "searchPath": ["<query-pack>"], "outputFormat": "sarif-latest" } -
Interpret results using
codeql_bqrs_interpret:{ "file": "<path-to-results.bqrs>", "format": "graphtext", "output": "<path-to-output.txt>", "t": ["kind=graph", "id=<query-id>"] } -
Study the AST output to identify:
- Relevant AST node classes
- Properties to query
- Relationships between nodes
- Predicates to use
-
Create query directory within your query pack:
<query-pack>/src/{QueryName}/ -
Write query (
{QueryName}.ql):/** * @name {Query Name} * @description {Detailed description} * @kind problem * @id {language}/tools/{query-name} */ import {language} from {ASTClass} element where // Implement logic based on AST analysis {conditions} select element, "{Message}"
-
Compile query using
codeql_query_compile:{ "queryPath": "<query-pack>/src/{QueryName}/{QueryName}.ql", "searchPath": ["<query-pack>"] }Fix any compilation errors before proceeding.
-
Run tests using
codeql_test_run:{ "testPath": "<query-pack>/test/{QueryName}", "searchPath": ["<query-pack>"] }Interpret Results:
- ✅ Tests pass: Move to refactoring
- ❌ Tests fail: Compare actual vs expected, adjust query, repeat
Once tests pass:
-
Improve Code Quality
- Extract complex logic to predicates
- Add helpful comments
- Improve variable names
- Enhance QLDoc documentation
-
Format query using
codeql_query_format:{ "queryPath": "<query-pack>/src/{QueryName}/{QueryName}.ql", "inPlace": true } -
Re-run tests using
codeql_test_runto verify refactoring didn't break anything.
- Add more test cases: Create additional test files (
test2.{ext},test3.{ext}) - Update expected results: Add new entries to
.expectedfile - Re-extract using
codeql_test_extract - Run tests and adjust query if needed
-
Install pack dependencies using
codeql_pack_install:{ "packPath": "<query-pack>/src" }{ "packPath": "<query-pack>/test" } -
Verify all tests pass by running tests for the entire query pack:
{ "testPath": "<query-pack>/test", "searchPath": ["<query-pack>"] }
This skill uses the following CodeQL Development MCP Server tools:
codeql_test_extract: Extract test databases from test codecodeql_test_run: Run CodeQL query tests and compare with expected resultscodeql_test_accept: Accept test results as new baselines (when appropriate)codeql_query_compile: Compile CodeQL queries and check for errorscodeql_query_run: Run queries against databases (e.g., PrintAST for AST analysis)codeql_query_format: Format CodeQL query filescodeql_bqrs_interpret: Interpret BQRS result files to human-readable formats (SARIF, CSV, graph formats)codeql_pack_install: Install query pack dependencies
- Purpose: Display AST structure for source files
- Use Case: Understanding code structure before writing queries
- Purpose: Find all functions called from a given function
- Use Case: Analyzing code dependencies and call chains
- Purpose: Find all functions that call a given function
- Use Case: Impact analysis and reverse dependencies
Before considering your query complete:
- Tests are comprehensive (positive, negative, edge cases)
- All tests pass
- Query compiles without warnings
- Code is well-documented with QLDoc comments
- Query follows CodeQL best practices
- All tests pass at language level
- Code is properly formatted
- ❌ Implementing query before writing tests
- ❌ Not analyzing AST structure with PrintAST first
- ❌ Accepting test results without verification
- ❌ Writing tests that are too complex
- ❌ Not testing edge cases
- ❌ Ignoring compilation warnings
- ❌ Skipping the refactoring phase
Your query development is successful when:
- All tests pass consistently
- Query behavior matches specification
- Code is clean and well-documented
- Integration tests pass
- Query can be invoked via MCP server
- Performance is acceptable for intended use cases