Creators guide
Codility provides a way to verify developers' skills in a completely automated manner. Tasks are meant to verify a particular skill or set of skills, by
-
setting the expectations to the programmer solving it (task description and starting code),
-
running automated checks against a given solution,
-
building a report with feedback and the score.
Tools
This documentation
Local runner
Local runner aims to mimic the Codility production runtime to provide a way to validate a given task locally, without the need to deploy it to Codility in the first place.
Installation
Local runner is packaged with all its dependencies with Docker and released to Docker Hub.
Since it uses Docker itself, it needs to control the OS Docker, which might be achieved by linking the socket file to the container.
A common way of automating it is to create a simple script:
#!/bin/bash PARAMS_TO_PASS="" while (( "$#" )); do case "$1" in -t|--task) TASK_PATH=$2 shift 2 ;; *) # preserve other arguments PARAMS_TO_PASS="$PARAMS_TO_PASS $1" shift ;; esac done if [[ ! -d $TASK_PATH ]]; then TASK_PATH="." fi TASK_PATH="$(cd "$TASK_PATH"; pwd)" # Calculate absolute path # Run Codility task runner utility with all the remaining args docker run \ --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $TASK_PATH:/task \ codility/local_runner:0.10.1 local_runner -t /task --host-task-path $TASK_PATH $PARAMS_TO_PASS
The downside is you need to be updating the version yourself.
Task specification
Everything needed
Structure
While Codility doesn’t enforce a specific structure, use this as a default:
task ├── Dockerfile # defines the runtime environment ├── codility.yml # describes how to execute the task ├── descriptions # descriptions visible to candidates │ └── en.md ├── solutions │ ├── golden.js # golden proves 100% points is possible │ ├── initial.js # the programmers' starting code │ ├── wrong_missing_null_check.js # additional wrong solutions verify the task quality │ └── wrong_no_type_checks.js └── src # contains tests and setup code
Every element is described in detail below.
Sometimes it is simpler to work on multiple tasks (sharing common traits) inside of a single repository. In this case feel free to use the following structure:
tasks/ ├── Dockerfile ├── src # shared source ├── task-a │ ├── codility.yml │ ├── descriptions │ │ └── en.md │ ├── solutions │ │ ├── golden.js │ │ ├── initial.js │ │ └── wrong_missing_null_check.js │ └── src # task-specific code, e.g. test cases └── task-b ├── codility.yml ├── descriptions │ └── en.md ├── solutions │ ├── golden.js │ ├── initial.js │ └── wrong_no_type_checks.js └── src
Docker image
We have chosen Docker to encapsulate the runtime environment due to it’s massive popularity and big community.
You may choose one of the provided images, or build your own. The
TODO: List of Codility pre-defined images.
Description
A text description of the task which is shown in the interface. Describe what precisely is expected from the candidate and what factors are important to get a maximum number of points. You can use Markdown formatting here.
Codility YAML
The entire task is described by a YAML file containing information like
-
description file location,
-
how to run the task code on a condidate’s solution,
-
author, title, etc.
Below you may find more information over the YAML file format.
Examples
The minimal file only requires a few fields:
format: '0.1' id: minimal title: Minimal task version: '1.12' tags: - javascript ui: description: descriptions.md solutions: golden: "golden.js" initial: "initial.js" execution: image: "minimal:1.12" assessment: cases: - name: All tests script: - echo running tests volumes: solution: /solution.js execution_output: /report
The more complex yaml shows most of the available functions.
format: '0.1' id: frontend_todolist title: Frontend todo-list version: '1.12' authors: john_doe tags: - frontend - javascript - react - angular variants: framework: title: Front-end framework select: one values: - angular4: image: angular preview_path: a_preview/index.html - react16: image: react preview_path: r_preview/index.html component_id: select: random values: - task_spec-counter - counter - counter-id done_class: select: random values: - is-done - done - checked - finished ui: description: descriptions/{{ language }}.md preview: "preview/{{ framework.preview_path }}" folds: - regex: '^describe\(' highlight: "js" languages: - en user_test_cases: example_input: | Multiline Example Input widget_type: "dialog" solutions: golden: "solutions/golden_{{ framework }}" initial: "solutions/begin_{{ framework }}" execution: image: "frontend_todolist_{{ framework.image }}:1.12" build: script: - echo "{{ done_class }}" - mkdir ./src - cp -R ./solution/project_data/src/* ./src - cp -R ./solution/project_data/src/* ./dist - cp -R ./solution/solution.ts ./src - ./node_modules/typescript/bin/tsc -p ./tsconfig.json - cp -R ./dist/* ./execution_output/ - rm -R ./execution_output/node_modules volumes: solution: /solution build_output: /compilation_output/{{ component_id }} assessment: # `name` is optional. # `script` should end up with a report. Multiple results per report are allowed. # output evaluator flattens reports into a single one. # if a case has a name, all tests from it's report have the name *overridden*. cases: - name: "The component should have a like button" obligatory: true dir: "testcase/01" kind: example script: - echo "{{ framework }}" - cp -R solution/* dist - MOCHA_FILE=./execution_output/junitresults.xml yarn mocha tests/test.js --grep "should have a like button" --timeout 5000 --reporter mocha-junit-reporter - name: "The component should have a proper format" dir: "testcase/02" kind: final script: - cp -R solution/* dist - MOCHA_FILE=./execution_output/junitresults.xml yarn mocha tests/test.js --grep "should have a proper format" --timeout 5000 --reporter mocha-junit-reporter volumes: task_data: /task/tests build_output: /execution_output execution_output: /report/{{ framework }} custom: - source: data/{{ case.dir }} target: /task_data output: evaluator: type: junit
Local runner will ensure it is compatible with a specified version of the YAML file.
Format version
The format string is there to make sure that the file format is consistent.
Codility may be changing the format before 1.0 in a non-backawrds compatible way.
The latest version is 0.1
.
format: '0.1'
Task id
id: frontend_todolist
Task id should be unique, and follow the pattern of [_a-zA-Z]{0,50}
(underscores and base alphabet chars up to a length of 256).
A good id
should relate to the described problem rather than a particular technology.
If a particular technology is essential to the task (e.g. REST
, shell
),
it might be a part of the name.
Fair | Better | Best |
---|---|---|
react_difficult |
todolist |
frontend_todolist |
django_post |
webapp_post |
webapp_login |
java_selenium_submit |
login_page |
qa_login_page |
Title
title: Frontend todo-list
Task name should be unique, and contain up to 256 characters.
name
should reflect the id
, but more readable.
id | name |
---|---|
frontend_todolist |
Front-end ToDo list |
qa_login_page |
QA login page |
Task version
version: '1.12'
Tasks are versioned for a few reasons:
-
to preserve the version during programmer’s solving session,
-
to have a cycle of reviewing and publishing.
Simply start with any version, and bump it whenever you’re releasing a new version of the same task.
Authors
Specifying an author is optional, but preferred. Author field is a simple one (string). In the future this will be connected to the creator’s account.
authors: john_doe
Tags
Tags are used for the task discovery in the task library.
tags: - frontend - javascript - react - angular
"android", "angular", "blockchain", "codelive", "coding", "distributed-programming", "django", "dotnet", "ethereum", "frontend", "groovy", "java", "javascript", "jvm", "kotlin", "labs", "laravel", "orm", "python", "qa", "react", "rest-assured", "robot-framework", "scala", "sql", "clojure", "selenium", "sequence-processing", "solidity", "spring", "text-processing", "web",
Variants
Variants the the powerful mechanism for making tasks more flexible and dynamic.
-
providing multiple programming languages,
-
providing several libraries to choose from,
-
making the task dynamic (more resilient to plagiarism).
UI
TODO
Solutions
TODO
Execution
TODO
Build
TODO
Assessment
TODO
Output
TODO
Task code
TODO