A concentrated dose of LSP testing power!
Provide an easy way to perform integration tests on language servers implemented in Rust.
First, add lspresso-shot as a dependency to your Rust project:
cargo add --dev lspresso-shotWrite a test:
#[test]
fn it_does_the_hover_thing() {
let hover_test_case = TestCase::new(
"Path to server",
TestFile::new("Source file name", "Contents")
)
.other_file( // Optional
TestFile::new("Other file name", "Other contents")
);
let cursor_pos = Position::new(1, 2);
lspresso_shot!(test_hover(
hover_test_case,
cursor_pos,
Some(&Hover {
range: Some(Range {
start: lsp_types::Position {
line: 1,
character: 2,
},
end: lsp_types::Position {
line: 3,
character: 4,
},
}),
contents: lsp_types::HoverContents::Markup(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: "Hover window contents here".to_string(),
})
})
));
}Or a benchmark:
fn blazingly_fast() {
let references_test_case = TestCase::new(
"Path to server",
TestFile::new("Source file name", "Contents")
);
let cursor_pos = Position::new(1, 2);
let include_declaration = true;
let measurements: Vec<Duration> = benchmark_references(
&test_case,
BenchmarkConfig::default(),
cursor_pos,
include_declaration,
);
}That's it!
Neovim must be available on your $PATH. See the project's documentation
for installation instructions. Versions at or later than 517ecb8
are necessary.
- The library's test corpus uses rust-analyzer. See
test-suite/src/*for examples of how to use the library. - TODO: Add asm-lsp/other LSPs here once it's being used.
-
If your server undergoes some sort of indexing process at startup before it's ready to service a given request, you need to account for this by specifying
ServerStartType::Progress(NonZeroU32, String)to the test case. TheNonZeroU32specifies whichendmessage to issue the request after (in case there are multiple). TheStringprovides the relevant progress token. -
String comparison of results: Many LSP client implementations do some post processing of responses returned by a given language server before displaying it to the user. Your expected response may need to be minimally altered from what you see in your editor in order for tests to pass.
-
Uri fields: If a response contains a Uri field with an absolute path, this field will be sanitizd to a relative path up to the test case's root directory. Your test case's expected results may need to be adjusted to reflect this.
-
Variance in LSP client implementation: The LSP Spec is somewhat loosely defined, leaving plenty of room for client implementations to behave differently from one another. This project utilizes neovim's, meaning that unexpected behavior may occur when your server is used with other editors' clients.
-
Ambiguous Deserialization of Response Types: Several response types specified in the LSP Spec are ambiguously deserialized to multiple types from their JSON representations. Because the LSP specification is defined over JSON RPC, this means that the value received by the LSP client may not match the value sent by your server. Any request affected by ambiguity will treat such values as equal in using the default comparison logic. Error messages may still display incorrect or misleading types, however.
- In addition to neovim, working on this project also requires having having
rust-analyzer rust-analyzer 1.87.0 (17067e9 2025-05-09) on your
$PATH, as it is used in the project's test suite.