I've talked about the design and evolution of cyber-dojo at two conferences this year.
First at NorDevCon in Norwich and then also at Agile on the Beach in Falmouth. Here's the slides.
cyber-dojo web server default start-points
This page holds the choices where you select both your language+testFramework (eg Java,Cucumber)
and your exercise (eg Print Diamond).
This page holds the customized choices (eg Tennis refactoring, Python unittest).
The language+testFramework list is served (by default) from a start-point image called languages.
The exercises list is served (by default) from a start-point image called exercises.
The custom list is served (by default) from a start-point image called custom.
A start-point image is created from a list of git-repo URLs, using the main cyber-dojo script, as follows:
The three default start-point images were created using the main cyber-dojo script, as follows:
Note the curl simply expands to a list of git-repo URLs, one for each of the most common language+testFrameworks. Each git-repo URL must contain a manifest.json file.
To use a different default start-point simply bring down the server, delete the one you wish to replace, create a new one with that default name, and bring the server back up. For example, to create a new languages start-point specifying just the Ruby test-frameworks:
This page holds the customized choices (eg Tennis refactoring, Python unittest).
The language+testFramework list is served (by default) from a start-point image called languages.
The exercises list is served (by default) from a start-point image called exercises.
The custom list is served (by default) from a start-point image called custom.
A start-point image is created from a list of git-repo URLs, using the main cyber-dojo script, as follows:
$ cyber-dojo start-point create NAME --languages <URL>...
The three default start-point images were created using the main cyber-dojo script, as follows:
$ LSP=https://raw.githubusercontent.com/cyber-dojo/languages-start-points
$ cyber-dojo start-point create languages \
--languages $(curl ${LSP}/master/start-points/common)
$ cyber-dojo start-point create exercises \
--exercises https://github.com/cyber-dojo/exercises-start-points
$ cyber-dojo start-point create custom \
--custom https://github.com/cyber-dojo/custom-start-points
Note the curl simply expands to a list of git-repo URLs, one for each of the most common language+testFrameworks. Each git-repo URL must contain a manifest.json file.
To use a different default start-point simply bring down the server, delete the one you wish to replace, create a new one with that default name, and bring the server back up. For example, to create a new languages start-point specifying just the Ruby test-frameworks:
$ cyber-dojo down
$ cyber-dojo start-point rm languages
$ cyber-dojo start-point create languages \
--languages \
https://github.com/cyber-dojo-languages/ruby-approval \
https://github.com/cyber-dojo-languages/ruby-cucumber \
https://github.com/cyber-dojo-languages/ruby-minitest \
https://github.com/cyber-dojo-languages/ruby-rspec \
https://github.com/cyber-dojo-languages/ruby-testunit
$ cyber-dojo up
cyber-dojo new release
The new release of cyber-dojo just went live :-)
- the setup start-points are now decoupled from the server and can be customized.
- the manifest.json format has changed accordingly.
- the instructions for running your own cyber-dojo server are new.

creating your own server start-points
cyber-dojo's architecture has customisable start-points.
eg with a languages start-point named adams/my_languages
eg with an exercises start-point named adams/my_exercises
eg with a combination
preparing your start-point
- Simply create a manifest.json file for each individual start-point.
eg$ mkdir -p douglas/one douglas/two $ touch douglas/one/manifest.json douglas/two/manifest.json - Edit each manifest.json files
Here's an explanation of the manifest.json format.
Here's an example. - Create a git repository in the top level directory.
eg$ cd douglas $ git init $ git add . $ git commit -m "first commit"
creating your start-point
Use the cyber-dojo script to create a new start-point naming the URL of the git repo (in this case ${PWD}). For example$ cd douglas
$ cyber-dojo start-point create adams/my_custom --custom ${PWD}
which attempts to create a custom start-point image called adams/my_custom from all the
files in the douglas directory.
If the creation fails the cyber-dojo script will print diagnostics.
starting your server with your start-point
eg with a custom start-point called adams/my_custom$ cyber-dojo up --custom=adams/my_custom
eg with a languages start-point named adams/my_languages
$ cyber-dojo up --languages=adams/my_languages
eg with an exercises start-point named adams/my_exercises
$ cyber-dojo up --exercises=adams/my_languages
eg with a combination
$ cyber-dojo up --languages=adams/my_languages --exercises=adams/my_exercises
adding a new language + test-framework to cyber-dojo
THE INFORMATION BELOW IS OUT OF DATE.
It will be updated properly soon.
Meanwhile, follow step 0 below, and then look at these examples from the cyber-dojo-languages github organization:
If you are adding a new unit-test-framework to an existing language skip this step.
For example, suppose you were building Lisp
For example, suppose your Lisp unit-test framework is called lunit
It will be updated properly soon.
Meanwhile, follow step 0 below, and then look at these examples from the cyber-dojo-languages github organization:
- repo for a docker-image for a language
- repo for a docker-image for a test-framework
0. Install docker
1. Create a docker-image for just the language
Make this docker-image unit-test-framework agnostic.If you are adding a new unit-test-framework to an existing language skip this step.
For example, suppose you were building Lisp
-
Create a new folder for your language
eg.$ md lisp -
In your language's folder, create a file called Dockerfile
$ cd Lisp $ touch DockerfileIf you can, base your new image on Alpine-linux as this will help keep images small. To do this make the first line of Dockerfile as followsFROM cyberdojofoundation/language-baseHere's one based on Alpine-linux (217 MB: C#) Dockerfile
Here's one not based on Alpine (Ubuntu 1.26 GB: Python) Dockerfile -
Use the
Dockerfile
to build a docker-image for your language.
For example$ docker build -t cyberdojofoundation/lisp .which, if it completes, creates a new docker-image calledcyberdojofoundation/lisp
using theDockerfile
(and build context) in.
(the current folder).
2. Create a docker-image for the language and test-framework
Repeat the same process, buildingFROM
the docker-image
you created in the previous step.For example, suppose your Lisp unit-test framework is called lunit
-
Create a new folder underneath your language folder
$ cd lisp $ md lunit
-
In your new test folder, create a file called
Dockerfile
$ cd lunit $ touch DockerfileThe first line of this file must name the language docker-image you built in the previous step.
Add lines for all the commands needed to install your unit-test framework...FROM cyberdojofoundation/lisp RUN apt-get install -y lispy-lunit RUN apt-get install -y ... -
Create a file called red_amber_green.rb
$ touch red_amber_green.rb
- In red_amber_green.rb write a Ruby lambda accepting three arguments.
For example, here is the
C#-NUnit red_amber_green.rb:
lambda { |stdout,stderr,status| output = stdout + stderr return :red if /^Errors and Failures:/.match(output) return :green if /^Tests run: (\d+), Errors: 0, Failures: 0/.match(output) return :amber }cyber-dojo uses this to determine the test's traffic-light colour by passing it the stdout, stderr, and status outcomes of the test run.
-
The Dockerfile for your language+testFramework must COPY red_amber_green.rb
into the /usr/local/bin folder of your image. For example:
FROM cyberdojofoundation/lisp RUN apt-get install -y lispy-lunit RUN apt-get install -y ... COPY red_amber_green.rb /usr/local/binI usually start with a red_amber_green.rb that simply returns :red. Then, once I have a start-point using the language+testFramework docker-image, I use cyber-dojo to gather outputs which I use to build up a working red_amber_green.rb
-
Use the
Dockerfile
to try and build your language+testFramework docker-image.
The name of an image takes the form hub-name/image-name. Do not include a version number in the image-name. For example$ docker build -t cyberdojofoundation/lisp_lunit .which, if it completes, creates a new docker image calledcyberdojofoundation/lisp_lunit
using theDockerfile
in.
(the current folder).
3. Use the language+testFramework docker-image in a new start-point
Use the new image name (eg cyberdojofoundation/lisp_lunit) in a new manifest.json file in a new start-point.cyber-dojo start-points manifest.json entries explained
Example: the
An array of two strings used to create Ruby regexs. The first one to match a red traffic light's test output, and the second one to match a green traffic light's test output.
An example for Python, unittest.
Defaults to [ ].
An array of strings. A strict subset of
Defaults to [ ].
An array of strings used to create Ruby regexs, used by cyber-dojo, like this
Defaults to [ ].
DEPRECATED. Instead, inside cyber-dojo.sh, use a trap handler to delete unwanted files. For example here's a trap handler for Ruby, Approval.
An integer between 1 and 20.
Defaults to 10.
DEPRECATED.
manifest.json
file for Java/JUnit looks like this:
{
"image_name": "cyberdojofoundation/java_junit:97411ac",
"display_name": "Java, JUnit",
"visible_filenames": [
"Hiker.java",
"HikerTest.java",
"cyber-dojo.sh"
],
"filename_extension": [ ".java" ],
"max_seconds": 10,
"tab_size": 4,
"progress_regexs" : [
"Tests run\\: (\\d)+,(\\s)+Failures\\: (\\d)+",
"OK \\((\\d)+ test(s)?\\)"
]
}
Required entries
"image_name": string
The name of the docker image used to run a container in whichcyber-dojo.sh
is executed.
Do not include any version numbers (eg of the compiler or test-framework).
The docker image must (currently) contain a file called red_amber_green.rb in the /usr/local/bin directory.
The runner service uses this to determine the
traffic-light colour of
each test run outcome. For example, here's the one for Java-JUnit.
"display_name": string
The name as it appears in the start-point setup pages. For example, "Java, JUnit" means that "Java, JUnit" will appear as a selectable entry. A single string typically with the major name first, then a comma, then the minor name."visible_filenames": [ string, string, ... ]
Filenames that will be visible in the browser's editor when an animal initially enter's a cyber-dojo. Each of these files must be a plain text file and exist in the manifest.json's directory. Filenames can be in nested sub-directories, eg"tests/HikerTest.java"
.
Must include "cyber-dojo.sh"
.
This is because cyber-dojo.sh
is the name
of the shell file assumed by the runner to be the start
point for running the tests. You can write any actions inside
cyber-dojo.sh
but clearly any programs it tries to run must be installed in the docker image_name.
For example, if cyber-dojo.sh
runs gcc
to compile C files then gcc
has
to be installed. If cyber-dojo.sh
runs javac
to compile java files then javac
has to be installed.
"filename_extension": [ string, string, ... ]
The extensions of source files. The first entry is also used when creating a new filename. Must be non-empty."tab_size": int
The number of spaces a tab character expands to in the editor. Must be an integer between 1 and 12.Optional entries
"progress_regexs": [ string, string ]
Used on the dashboard to show the test output line (which often contains the number of passing and failing tests) of each animal's most recent red/green traffic light. Useful when your practice session starts from a large number of pre-written tests and you wish to monitor the progress of each animal.An array of two strings used to create Ruby regexs. The first one to match a red traffic light's test output, and the second one to match a green traffic light's test output.
An example for Python, unittest.
Defaults to [ ].
"highlight_filenames": [ string, string, ... ]
Filenames whose appearance is highlighted in the browser. This can be useful if you have many"visible_filenames"
and want
to mark which files form the focus of the practice.
An array of strings. A strict subset of
"visible_filenames"
.
Defaults to [ ].
"hidden_filenames": [ string, string, ... ]
cyber-dojo.sh may create extra files (eg profiling stats). All text-files created under /sandbox are returned to the browser unless their name matches any of these string regexs.An array of strings used to create Ruby regexs, used by cyber-dojo, like this
Regexp.new(string)
.
For example, to hide files ending in .d you can use the following string ".*\\.d"
Defaults to [ ].
DEPRECATED. Instead, inside cyber-dojo.sh, use a trap handler to delete unwanted files. For example here's a trap handler for Ruby, Approval.
"max_seconds": int
The maximum number of secondscyber-dojo.sh
has to complete.
An integer between 1 and 20.
Defaults to 10.
DEPRECATED.
Subscribe to:
Posts (Atom)