diff --git a/sql-to-dot.sed b/sql-to-dot.sed
new file mode 100755
index 0000000..07b2989
--- /dev/null
+++ b/sql-to-dot.sed
@@ -0,0 +1,81 @@
+#! /bin/sed -nf
+1i\
+/** @page database Database Schema\
+\
+@dot\
+digraph schema {
+
+# get everithing on one single line
+H;$!d;$x
+
+# remove all single-line comment lines
+s/\n--[^\n]*//g
+
+# reduce spaces
+s,\t\| \+, ,g
+
+# remove multiline comments
+:f;s,\(.*\)/\*.*\*/[ \n]*;*,\1,g;tf
+
+# remove empty lines
+s,\n\+,\n,g
+
+# remove unknown commands
+s,\(;\|\n\) *\(DELIMITER\|USE\|DROP\|CREATE[ \n]\+DATABASE\)[ \n]\+[^;]*;\+,,ig
+
+# convert special characters within quotes
+:a;s/^\(\([^"]*"[^",]*"\)*[^"]*"[^"]*\),\([^"]*".*\)/\1\##COMMA##\3/g;ta
+:c;s/^\(\([^']*'[^',]*'\)*[^']*'[^']*\),\([^']*'.*\)/\1\##COMMA##\3/g;tc
+
+# backup everything to the buffer
+# then analyze only on one create table
+:i
+h
+s,.*\(create[ \n]\+table[^;]*;\).*,\1,ig
+
+# start html table node
+s|CREATE[ \n]\+TABLE[ \n]\+\(if[ \n]\+not[ \n]\+exists[ \n]\+\)\?`\?\(\w\+\)`\?| \2\n [shape=none, margin=0, label=<\n
\n \2 |
|ig
+
+# remove key definitions
+s/[),][\n ]*\(PRIMARY[ \n]\+\)\?KEY[ \n]\+[^(]*([^)]*)//gi
+
+# move foreign keys as relation to the end
+:b;s/\(\w\+\)\([^;]*\)FOREIGN[\n ]\+KEY[ \n]*([ \n]*`\?\([a-z]\+\)`\?[ \n]*)[ \n]*REFERENCES[ \n]*`\?\([a-z]\+\)`\?[ \n]*([ \n]*`\?\([a-z]\+\)`\?[ \n]*)[ \n]*\([^,)]*\)\([,)].*\)/\1\2\7\n \1:\3 -> \4:\5 [label="\6"]##SEMICOLON##/ig;tb
+
+# create table rows
+s|[(,][ \n]*`\?\(\w\+\)`\?[ \n]\+\(\w\+\(([^)]\+)\)\?\)[ \n]*\([^,)]*\)[ \n]\+COMMENT[ \n]*["']\([^"']*\)["'][ \n]*|\n \1 | \2 | \4 | \5 |
|gi
+s|[(,][ \n]*`\?\(\w\+\)`\?[ \n]\+\(\w\+\(([^)]\+)\)\?\)[ \n]*\([^,)]*\)|\n \1 | \2 | \4 |
|g
+
+# add line breaks for long lines
+s|\(]*>[^<]\{30,40\}\)[ \n]\+\([^<]\{20,\} | \)|\1
\2|g
+#:d;s|\(
[^<]\{30,40\}\)[ \n]\+\([^<]\{20,\}\)|\1
\2|g;td
+
+# add table comment below
+:k;tk
+s|[ \n]*)[^)]*COMMENT[ \n]*=[ \n]*["']\?\([^"']*\)["']\?[^;]*|\n \1 |
|ig;th
+s|)[^);]*;|\n;|ig
+:h
+
+# cleanup comment below, add line breaksfor long lines
+s|\(]*>[^<]\{60,80\}\)[ \n]\+\([^<]\{30,\} | \)|\1
\2|g
+#:e;s|\(
[^<]\{60,80\}\)[ \n]\+\([^<]\{30,\}\)|\1
\2|g;te
+
+# close table
+s|;|\n
\n >];|ig
+
+# convert ##COMMA## to ,
+s|##COMMA##|,|g
+# convert ##SEMICOLON## to ;
+s,##SEMICOLON##,;,g
+
+# print one table
+p
+# get buffer back and remove the table that has just been analyzed
+x
+s,\(.*\)create[ \n]\+table[^;]*;\(.*\),\1\2,ig
+ti
+
+$a\
+}\
+@enddot\
+*/
diff --git a/test/runtests.sh b/test/runtests.sh
new file mode 100644
index 0000000..262755c
--- /dev/null
+++ b/test/runtests.sh
@@ -0,0 +1,120 @@
+#!/bin/bash -e
+
+#check for a text in a docker volume log
+function check() {
+ if test $(docker inspect -f {{.State.Running}} $1) = "false"; then
+ echo
+ echo "**** ERROR: container $1 not running"
+ exit 1
+ fi
+ docker logs $1 2>&1 | grep -q "$2"
+}
+
+# call with volume name
+function wait_for_mysql() {
+ check $1 "mysqld: ready for connections"
+}
+
+# run a countdown and call a check function
+# $1: expected time in seconds
+# $2-: check function
+function countdown() {
+ set +x
+ expect=$1
+ shift
+ max=$1
+ shift
+ for ((i=0; i<$((expect+max)); ++i)); do
+ echo -en "\rPlease wait: $((expect-i))s "
+ $* && break || sleep 1
+ done
+ echo -e "\rdone in ${i}s: $* "
+ echo
+ set -x
+}
+
+# should not be called with sudo root
+if test "$(whoami)" = "root"; then
+ echo "**** ERROR: call as non root user"
+ exit 1
+fi
+
+# option checks
+NEED_XVFB=0
+NEED_DOCKER=0
+NEED_WEBTESTER=0
+while test $# -gt 0; do
+ case "$1" in
+ (--help|-h)
+ echo "$0 [OPTIONS] [PORTS ]"
+ echo
+ echo "OPTIONS:"
+ echo
+ exit 0
+ ;;
+ (*) echo "**** ERROR: unknown option '$1', try --help"; exit 1;;
+ esac
+ if test $# -eq 0; then
+ echo "**** ERROR: missing value, try --help"; exit 1;
+ fi
+ shift
+done
+
+error=0;
+
+# test for xvfb (needed by webtester)
+if test ${NEED_XVFB} -eq 1 -a \! -e "$(which xvfb-run)"; then
+ echo "**** ERROR: XVFB Not Installed"
+ echo "you need to install xvfb"
+ echo "please execute as root:"
+ echo " apt-get install xvfb"
+ error=1
+fi
+
+# test for docker if needed
+if test ${NEED_DOCKER} -eq 1 -a \! -e "$(which docker)"; then
+ echo "**** ERROR: Docker Not Installed"
+ echo "you need to install the latest docker"
+ echo "please execute as root:"
+ echo " apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 \\"
+ echo " --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9"
+ echo " echo 'deb https://get.docker.io/ubuntu docker main' \\"
+ echo " > /etc/apt/sources.list.d/docker.list"
+ echo " apt-get update"
+ echo " apt-get install lxc-docker"
+ echo " adduser $(whoami) docker"
+ echo "you need to add the following line to /etc/default/docker:"
+ echo ' DOCKER_OPTS="--insecure-registry dev0004:5000"'
+ echo "logout $(whoami) and login again to run $(whoami) with group docker"
+ echo "additionals note:"
+ echo " if you run docker inside a VM (not recommended), you probably"
+ echo " need to foollow the instructions in chapter \"Changing Bridge"
+ echo " Subnetwork\" on https://marc.wäckerlin.ch/computer/docker-overview"
+ echo "introduction to docker, see:"
+ echo " https://marc.wäckerlin.ch/computer/docker-overview"
+ error=1
+fi
+
+# check for webtester
+if test ${NEED_WEBTESTER} -eq 1 -a \! -e "$(which webrunner)"; then
+ echo "**** ERROR: Webtester Not Installed"
+ echo "you need to install webtester"
+ echo "please execute as root:"
+ echo " apt-get install -y wget software-properties-common apt-transport-https"
+ echo " apt-add-repository https://dev.marc.waeckerlin.org/repository"
+ echo " wget -O- https://dev.marc.waeckerlin.org/repository/PublicKey \\"
+ echo " | apt-key add -"
+ echo " apt-get update -y"
+ echo " apt-get install -y webtester"
+ echo "more information, see:"
+ echo " https://dev.marc.waeckerlin.org/redmine/projects/webtester"
+ error=1
+fi
+
+if test "$error" = "1"; then
+ exit 1
+fi
+
+set -x
+
+# Add tests here
diff --git a/webtester.desktop.in b/webtester.desktop.in
new file mode 100644
index 0000000..07d8436
--- /dev/null
+++ b/webtester.desktop.in
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Application
+Name=webtester
+GenericName=webtester
+Comment=@DESCRIPTION@
+Icon=@prefix@/share/@PACKAGE_NAME@/@PACKAGE_ICON@
+Exec=webtester %u
+Terminal=false
+Categories=Qt;Utility;