(Figuratively) Eating Tritium

It’s canon that developers should use the products they make.

Thinking of my favorite software and it seems most is also beloved by the developers who write it. From git to vim or emacs all the way through to VS Code and even Chrome and Spotify. These products are either literally self-hosting, as in the case of Git and the text editors, or are dogfooded every day by the developers building them like Chrome and Spotify.

I understand it’s especially true in game development where drilling down on the correct “game feel” requires hours of concerted effort by the folks who know where the corner cases are hidden. John Romero apparently spent huge amounts of time playing DOOM during its development, for example, and we know how that turned out. I thus hypothesize the more time I can spend using my tool while building it, the more I’ll feel the small annoyances and fix them and the better Tritium will be.

But Tritium isn’t a developer tool or video game, it’s a legal tech, and I don’t spend my days reviewing legal documents anymore.

I could run simulations, but the risk there is over-fitting or prematurely optimizing for something that turns out to be purely hypothetical. I might avoid the uncomfortable corner cases subconsciously without discovering that they’re more common than I thought.

No, the best products are developed using themselves and Tritium does afford some creative ways to road test it during development.

Press Releases and Blogging

The most straightforward way is to write actual Word documents with Tritium.

In my case, it’s press releases.

They’re almost too trivial to bother with except for the side effects. I manage them the way I expect users to manage documents. They’re stored on a deliberately laggy network drive to get a feel for that.

Press releases in Tritium

Once the iManage integration comes through, we’ll move them up to an iManage instance to road test that integration.

This blog is composed in a similar manner.

I take the Word document and use ChatGPT to convert the contents into HTML.

It’s tempting to add an “export to HTML” feature, but I have to be careful here because I’m not re-writing FrontPage. I’m building an IDE for lawyers, and many lawyers don’t even know what HTML means.

I have to ignore the desire to optimize the image insertion and manipulation features, since those aren’t the most important features. Thus, the blogs on here tend to be basic.

Integration Tests

One of the best things I’ve done so far is develop a sort of scripting language for Tritium through which I run integration tests.

The initial idea was just intended to provide a way to interact programmatically end-to-end with Tritium. It occurred to me that instead of separate scripts or more .rs files in the VS code tree, I could write them as Word documents.

Here’s an example.

The basic idea is to write a script in the first section as a series of keystrokes. Here, we have:

Ctrl+N
(☢ fused with tritium ☢)
End
Home
Right
Right
Delete
Delete
Delete
Delete
Delete
(boosted)
Ctrl+S
Ctrl+F4

The next section(s) are the expected result from the keystrokes in rich text format.

☢ boosted with tritium ☢

libtritium brings with it an integration_test binary that takes a docx file as a command-line argument, reads it in as a test and executes it.

Running integration tests as Tritium scripts is great, but it feels clunky to dial them up from the command line. And using the debugger is harder. I have to manually edit the main.rs and run the application from VS Code in debugging.

What would happen, though, if we integrated something easier right into the UI of the debug builds of the IDE?

This:

In the video you can see I right-click on the file tab, then click “Run as Test”. The test fails, and the failure is highlighted in the VS Code terminal. This is an integration test set up for fixing a bug that surfaced while writing this blog post.

Under the hood, the runner is quite simple using immediate mode egui given a context menu named ui:

let run_as_integration_test = egui::Button::new("Run as Test");
if ui.add(run_as_integration_test).clicked() { 
    if let Ok(document) = reference.read() { 
        if let Some(path) = document.path.as_ref() { 
            let Ok(mut spawn) = std::process::Command::new("cargo")
                .arg("run")
                .arg("--bin")
                .arg("integration_test")
                .arg(path)
                .spawn() else {
                log::error!("Failed to start Integration Test at: {:?}", path);
                return;
            };
            let Ok(result) = spawn.wait() else {
                log::error!("Failed to wait for Integration Test at: {:?}", path);
                return;
            };
            if result.success() {
                log::info!("Integration Test at: {:?} passed.", path);
            } else {
                log::info!("Integration Test at: {:?} failed.", path);
            }
        }
    }
}

Interestingly, the forked process seems to inherit VS Code’s attached debugger, although I haven’t tested that yet. That should mean I can set a breakpoint in the VS Code, run the integration test, and step through the code in VS Code.

Running integration tests from within Tritium thus makes it easier to both build and run my test from within Tritium than to set them up in code. So I get to double up on the qualitative and quantitative testings.

I’ve now wired this up to my smoke tester, and it makes for some fun chaotic smoke testing that I’ll describe another day.

Thanks for reading.