Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time

The issue with writing long complex tutorials

When building a large and complex software project, you’d like to be able to make a change to the code base and be sure that the software still works as intended. Nowadays, folks use automated tests to check that things work after code changes.

Let’s say you’re working on a long and complex tutorial for building some kind of software application. At some point, you decide to change something in the middle of the tutorial. Now, how do you know that your tutorial still works? Experienced tutorial writers know that one option is to occasionally go through the entire tutorial again to make sure that the steps still lead to the expected resultant project. Another option is to rely on readers of the tutorial to report issues after any changes are made.

Or, you can make your tutorial executable and unit tested.

Executable tutorial

The idea with an executable tutorial is that the steps that the user is expected to take are in a machine readable format. Then, the whole tutorial can be executed at any point to make sure that the steps still lead to the expected project.

Unit tested tutorial

You can include steps in your tutorial to unit test your project. Then if your project tests pass, you can consider your tutorial to also be in a passing state. By having your generated project be unit tested, your tutorial is also tested.

Course writers

Authors of courses on sites like Udemy or Pluralsight could benefit from first writing their course as an executable tutorial. They can then use the tutorial as their script when recording videos, confident that the instructions lead to a working project (without having to go through the steps manually, again and again).

Example 1 - Saturn project (F#)

Saturn is an MVC web framework for F#.

MvcMovieSaturnTutorial is a tutorial for building a simple web app in Saturn. That markdown file is generated from this source file which is written in PowerShell. This script is used to convert the source file to markdown.

English-language change descriptions

Programming tutorials contain instructions to the reader regarding what file to change and what to change about it.

Here’s a screenshot from the MvcMovieSaturnTutorial which shows an example of how file changes are described:


Here’s the part of the source document from which that is generated:

$file = '.\src\MvcMovieSaturn\Movies\MoviesModel.fs'

$original_text = @"
    let validators = [
      fun u -> if isNull u.Id then Some ("Id", "Id shouldn't be empty") else None

$replacement_text = @"
    let validators = []

Edit $file -Replacing $original_text -With $replacement_text

As you can see there, the filename to be edited is stored in the variable $file. The text that is to be replaced is stored in $original_text. Finally, the new text goes in $replacement_text. Then the Edit function is called:

Edit $file -Replacing $original_text -With $replacement_text

Example 2 - ASP.NET Core project

The next example is a tutorial for building a very simple link aggregator application in ASP.NET core.

diff-style change descriptions

In this tutorial, I took a different approach to the change descriptions. I simply included the output of git diff:


I think the english-language change descriptions from example 1 are visually nicer. However, the diff-style ones are obviously much easier to create. With the former, I had to manually create each change description. With the latter, all I need to do is git diff, and include that in the tutorial source.

Something to consider is having a way to automatically convert from git diff output to the friendlier style.

Automated screenshots

Many tutorials often contain screenshots. Some issues with these:

  • Generating these can be labor intensive
  • If you update the tutorial, the screenshots have to be updated
  • Tutorial writers often let the screenshots fall out of sync with the tutorial.

The LinkAggregator tutorial contains a screenshot at the beginning. This screenshot is generated when the source file is run.

Using Canopy for screenshots

Canopy, an F# web testing framework, is used to write the tests for LinkAggregator. In these tests I have a step to take a screenshot:

"take screenshot" &&& fun _ ->

    resize (850, 450)
    screenshot "." "screenshot-links" |> ignore

This solves the issue of screenshots being out of date. Each time I run the tutorial source file to test it, fresh screenshots are generated.

Future areas to explore

Cross-platform executable tutorials

The two examples discussed have only been tested on Windows.

PowerShell works on Windows, Linux, and macOS. So conceivably, it could be used to write tutorials which work on all three platforms.

Source file in other lanuages

The source files in two examples discussed are written in PowerShell.

Other scripting languages comparable to PowerShell could conceivably be used to author source files.

DSL for tutorial source files

PowerShell was quite a comfortable language for writing the tutorial source files.

That said, it maybe worth exploring a DSL designed for authoring source files. Perhaps Racket or Haskell could be used for such a DSL.

Alternate presentation of file change descriptions

In some programming books, file changes that the user is expected to make are sometimes indicated by displaying the entire file, but bolding lines that the user should edit. Offering this style of change description to the user would be nice. It may also be nice to have it be up to the user what style to see; i.e. show diff-style by default, but allow the user to switch to the whole-file view on demand.

Targets besides markdown

It would be nice to target a document format that is richer than standard github rendered markdown. An automatically generated table of contents would be nice, for example.


If you write an executable tutorial and would like to share your work, feel free to post a link to your work in the discussions.

If you know of any tutorials written in such a style, also feel free to post these in the discussions.