Skip to content
Skills Library
Programming · Testing

write-test

/write-test

Use when adding or modifying JETLS tests. Covers test file and module structure, `@testset` organization, `let` blocks, `withserver` usage, cached syntax trees in helpers that call features directly, and when subroutine tests are sufficient for language-server features.

Repository
JETLS.jl ↗
Licence
MIT
Last repository change
27.10.2026

Assessment and security

95/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content30 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 27.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Use when adding or modifying JETLS tests. Covers test file and module structure, `@testset` organization, `let` blocks, `withserver` usage, cached syntax trees in helpers that call features directly, and when subroutine tests are sufficient for language-server features.

Original author description

Use when adding or modifying JETLS tests. Covers test file and module structure, `@testset` organization, `let` blocks, `withserver` usage, cached syntax trees in helpers that call features directly, and when subroutine tests are sufficient for language-server features.

How it works

  1. Test file structure
  2. Organizing test code
  3. Language-server feature tests
  4. After writing tests
Original SKILL.md headings · 131 lines, 479 words
SKILL.md preview
---
name: write-test
description: >
  Use when adding or modifying JETLS tests. Covers test file and module
  structure, `@testset` organization, `let` blocks, `withserver` usage,
  cached syntax trees in helpers that call features directly, and when
  subroutine tests are sufficient for language-server features.
---

# Write JETLS tests

Use this skill when you add new tests or modify existing JETLS test code.

## Test file structure

Test code for new language server features should be written in files that
define independent module spaces with a `test_` prefix. Include those files
from `JETLSCore/test/runtests.jl`.

This lets each test file run independently from the REPL.

For example, `JETLSCore/test/test_completions.jl` should look like:

```julia
module test_completions
using Test
...
end # module test_completions
```

Then include it from `JETLSCore/test/runtests.jl` like this:

```julia
@testset "JETLS.jl" begin
    ...
    @testset "completions" include("test_completions.jl")
    ...
end
```

## Organizing test code

Use `@testset "testset name"` to organize tests cleanly.

For code clarity, avoid placing `using`, `import`, or `struct` definitions
inside `@testset` blocks unless it is specifically necessary.
Prefer top-level definitions.

Use `let` blocks to avoid unintentionally reusing names across test cases,
unless a helper function or `do` block already provides local scope.

Example:

```julia
module test_completions

using Test
using JETLSCore: some_completion_func

function testcase_util(s::AbstractString)
    ...
end
function with_testcase(s::AbstractString)
    ...
end

@testset "some_completion_func" begin
    let s = "..."
        ret = some_completion_func(testcase_util(s))
        @test test_with(ret)
    end
    let s = "..."
        ret = some_completion_func(testcase_util(s))
        @test test_with(ret)
    end

    with_testcase(s) do case
        ret = some_completion_func(case)
        @test test_with(ret)
    end
end

end # module test_completions
```

## Language-server feature tests

Testing language server functionality is challenging. To fully test such
functionality, you need to start a server loop and send requests that mimic
realistic user interactions.

For those tests, use `withserver` from
[`JETLSCore/test/setup.jl`](../../../JETLSCore/test/setup.jl).
Refer to [`JETLSCore/test/test_full_lifecycle.jl`](../../../JETLSCore/test/test_full_lifecycle.jl)
as an example.

A good pattern is [`JETLSCore/test/test_definition.jl`](../../../JETLSCore/test/test_definition.jl):
it keeps the full `withserver` coverage to one `request/response sanity` test
for the `DidOpen` → analysis → `DefinitionRequest` path, while most cases use
`definition_test` to call `find_definition` directly and assert on returned
locations. Prefer this split for LSP handlers.

### Cached syntax trees

Requests on a synchronized document share the cached syntax tree of its
`FileInfo` without copying it, so no feature may mutate that tree. Under
`JETLS_TEST_MODE`, JETLS records a fingerprint of each cached tree and
`JETLSCore.check_syntax_tree0(fi)` throws if the tree has changed since.
`withserver` runs this check for every open document when the test finishes.

Helpers that construct their own `FileInfo` and call a feature directly
should construct it with `cache_tree0 = true`, as `cache_file_info!` does for
synchronized documents, and call `JETLSCore.check_syntax_tree0(fi)` after the
feature call:

```julia
function find_definition(text::AbstractString, pos::Position)
    server = JETLSCore.Server()
    filename = joinpath(@__DIR__, "testfile_$(gensym(:definition)).jl")
    fi = JETLSCore.FileInfo(#=version=#0, text, filename; cache_tree0 = true)
    furi = filename2uri(filename)
    JETLSCore.store!(server.state.file_cache) do cache
        Base.PersistentDict(cache, furi => fi), nothing
    end
    result = JETLSCore.find_definition(server, furi, fi, pos)
    JETLSCore.check_syntax_tree0(fi)
    return result
end
```

Leave `cache_tree0` unset when the `FileInfo` is only used to convert
positions or stands for a file that is not open in the editor, since JETLS
doesn't cache a tree for such files in production either.

## After writing tests

When you add or modify tests, use the [`run-test`](../run-test/SKILL.md)
workflow to run the most specific relevant test command.

Versions

RepositoryScoreLicence
This page · aviatesk/JETLS.jl95MIT
markneonin/paneline96MIT

Database snapshot: 13.11.2026 · package version 64f9a5ab0b5e (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 100run-test
    Use when choosing or running JETLS tests after code changes. Prefer component-specific tests, avoid the full suite unless needed, and use TestRunner for focused iteration.
  • 100testing
    Helps write and organize tests. Use when creating unit tests, integration tests, or E2E tests. Covers test patterns, mocking strategies, and test organization.
  • 90write-tests
    Writes or changes tests in this repository to its quality bar, with the right helpers and layer. Use when adding, fixing or reviewing tests, when a change "needs a test", or when deciding whether a test may change.
  • 100write-e2e-test
    Write a Playwright E2E test for Bruno. Use when adding or modifying tests under tests/, creating a new test suite, or reproducing a bug as an e2e spec.
  • 100write-tests
    Write unit and integration tests. Use when the user says "write tests for this", "add test coverage", "how do I test this", "TDD", "red green refactor", "unit test this function", "test this module", "I need tests for", or has code that lacks tests - even if they don't explicitly say "write tests".
  • 100generate
    Generate Playwright tests. Use when user says "write tests", "generate tests", "add tests for", "test this component", "e2e test", "create test for", "test this page", or "test this feature".

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.