Skip to content

Commit bac0e0c

Browse files
Add documentation for custom test framework reporting (#3640)
* Add documentation for custom test framework reporting * Apply suggestions from code review Co-authored-by: Alex Rocha <[email protected]> --------- Co-authored-by: Alex Rocha <[email protected]>
1 parent 6de4e8d commit bac0e0c

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

jekyll/test_framework_addons.markdown

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ There are 3 main parts for contributing support for a new framework:
1717

1818
- [Test discovery](#test-discovery): identifying tests within the codebase and their structure
1919
- [Command resolution](#command-resolution): determining how to execute a specific test or group of tests
20-
- Custom reporting: displaying test execution results in the test explorer
20+
- [Custom reporting](#custom-reporting): displaying test execution results in the test explorer
2121

2222
## Test discovery
2323

@@ -331,3 +331,70 @@ end
331331
```
332332

333333
You can refer to implementation examples for [Minitest and Test Unit](https://github.com/Shopify/ruby-lsp/blob/d86f4d4c567a2a3f8ae6f69caa10e21c4066e23e/lib/ruby_lsp/listeners/test_style.rb#L10) or [Rails](https://github.com/Shopify/ruby-lsp-rails/blob/cb9556d454c8bb20a1a73a99c8deb8788a520007/lib/ruby_lsp/ruby_lsp_rails/rails_test_style.rb#L11).
334+
335+
## Custom reporting
336+
337+
To report test execution results to the extension side, frameworks should be hooked up with a custom reporter that sends
338+
JSON RPC events. To hook up the custom reporter, add-ons should include all CLI arguments necessary as part of
339+
resolving test commands. For example:
340+
341+
```shell
342+
bundle exec my_framework /path/to/project/test/foo_test.rb --reporter MyFrameworkLspReporter
343+
```
344+
345+
To implement the reporter, the Ruby LSP already provides helpers for all of the supported events. It is a matter of
346+
ensuring that all events are produced when the test framework performs the associated actions.
347+
348+
```ruby
349+
# An Lsp reporter for our example test framework
350+
# See lib/ruby_lsp/test_reporters/lsp_reporter.rb for all available helpers and events
351+
class MyFrameworkGemLspReporter
352+
# Record that an example started running. This shows the example as running in the UI
353+
def test_started_running(test_object)
354+
id = "#{test_object.class.name}##{test_object.method_name}"
355+
uri = URI::Generic.from_path(path: test_object.file_path)
356+
RubyLsp::LspReporter.instance.start_test(id: id, uri: uri, line: test_object.line_number)
357+
end
358+
359+
# Record that an example passed, which shows a green checkmark in the UI
360+
def test_passed(test_object)
361+
RubyLsp::LspReporter.instance.record_pass(id: id, uri: uri)
362+
end
363+
364+
# Record that an example errored, which shows a red X in the UI and displays the exception message
365+
def test_errored(test_object)
366+
RubyLsp::LspReporter.instance.record_skip(id: id, uri: uri, message: "Test errored because...")
367+
end
368+
369+
# Record that an example failed, which shows a red X in the UI and displays the failure message
370+
def test_failed(test_object)
371+
RubyLsp::LspReporter.instance.record_fail(id: id, uri: uri, message: "Test failed because...")
372+
end
373+
374+
# Record that an example skipped, which shows a skipped status in the UI
375+
def test_skipped(test_object)
376+
RubyLsp::LspReporter.instance.record_skip(id: id, uri: uri)
377+
end
378+
379+
# Normal shutdown flow, when all tests ran without crashing the test process itself
380+
def after_all_tests_finished_running
381+
LspReporter.instance.shutdown
382+
end
383+
end
384+
385+
# This is required to cleanup the explorer in case the normal execution of tests errors. For example, if the user
386+
# writes a bad require and the test process crashes before even starting to run examples
387+
MyFrameworkGem.after_run_is_completed do
388+
RubyLsp::LspReporter.instance.at_exit
389+
end
390+
```
391+
392+
{: .important }
393+
The IDs and URIs used to report results **must match** the ones used during test discovery to ensure that the outcomes
394+
are associated with the right items.
395+
396+
{: .note }
397+
If your test framework is based on Minitest or Test Unit and leverages their reporting structure, you may not need to
398+
add custom reporters. Instead, you can simply rely on the ones automatically registered and provided by the Ruby LSP.
399+
400+
See our reporters for [Minitest](https://github.com/Shopify/ruby-lsp/blob/main/lib/ruby_lsp/test_reporters/minitest_reporter.rb) and [Test Unit](https://github.com/Shopify/ruby-lsp/blob/main/lib/ruby_lsp/test_reporters/test_unit_reporter.rb) as examples.

0 commit comments

Comments
 (0)