Run tests on Travis CI
diff --git a/.travis.yml b/.travis.yml
index 3eb6ce63..f64a78ee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,14 @@ language:
   - generic
 
 before_install:
-  - docker-compose up -d
-  - docker ps
+  - docker-compose build
   - docker images
+  - docker-compose -f docker-compose.yml -f docker-compose.debug.yml up -d
+  - docker-compose ps
+
+script:
+  - sleep 3
+  - curl http://localhost:8002
+  - docker-compose logs --no-color
+  - docker logs chtsh
+  - CHEATSH_TEST_STANDALONE=NO bash tests/run-tests.sh
diff --git a/Dockerfile b/Dockerfile
index e78be409..e41aa0a5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,5 +15,5 @@ RUN mkdir -p /root/.cheat.sh/log/ \
 
 # installing server dependencies
 RUN apk add --update --no-cache py3-jinja2 py3-flask bash gawk
-ENTRYPOINT ["python3"]
-CMD ["bin/srv.py"]
+ENTRYPOINT ["python3", "-u", "bin/srv.py"]
+CMD [""]
diff --git a/README.md b/README.md
index 98d4c6ef..86284cc2 100644
--- a/README.md
+++ b/README.md
@@ -447,8 +447,16 @@ scoop install cht
 
 ### Docker
 
-Currently, the easiest way to get a self-hosted instance running is by using the docker-compose.yml file provided in the extra/docker folder.
-This pulls down the latest image with baked in cheatsheets and starts the app and a Redis instance to back it, making the service available on port 8002 of the local host. This is currently an early implementation and should probably not be used for anything outside of internal/dev/personal use right now.
+Currently, the easiest way to get a self-hosted instance running is by using
+the `docker-compose.yml` file.
+
+    docker-compose up
+
+This builds and runs the image with baked in cheatsheets and starts the app
+and a Redis instance to back it, making the service available at
+http://localhost:8002 This is currently an early implementation and should
+probably not be used for anything outside of internal/dev/personal use right
+now.
 
 ## Editors integration
 
diff --git a/bin/clean_cache.py b/bin/clean_cache.py
index 1b4fe630..bc19aa84 100644
--- a/bin/clean_cache.py
+++ b/bin/clean_cache.py
@@ -1,6 +1,6 @@
 import sys
 import redis
-REDIS = redis.StrictRedis(host='localhost', port=6379, db=0)
+REDIS = redis.Redis(host='localhost', port=6379, db=0)
 
 for key in sys.argv[1:]:
     REDIS.delete(key)
diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml
new file mode 100644
index 00000000..56c5e9c9
--- /dev/null
+++ b/docker-compose.debug.yml
@@ -0,0 +1,8 @@
+# Compose override to add --debug option to bin/srv.py
+# call to print tracebacks on errors to stdout.
+#
+# See https://docs.docker.com/compose/extends/
+version: '2'
+services:
+  app:
+    command: "--debug"
diff --git a/docker-compose.yml b/docker-compose.yml
index 589033c6..9e5f58f2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,10 +1,13 @@
 version: '2'
 services:
   app:
-    build:
-      context: .
+    build: .
+    image: cheat.sh
+    container_name: chtsh
     depends_on:
       - redis
+    environment:
+      - CHEATSH_CACHE_REDIS_HOST=redis
     ports:
       - "8002:8002"
   redis:
diff --git a/lib/cache.py b/lib/cache.py
index 5f552763..8e2b1263 100644
--- a/lib/cache.py
+++ b/lib/cache.py
@@ -19,7 +19,7 @@
 _REDIS = None
 if CONFIG['cache.type'] == 'redis':
     import redis
-    _REDIS = redis.StrictRedis(
+    _REDIS = redis.Redis(
         host=CONFIG['cache.redis.host'],
         port=CONFIG['cache.redis.port'],
         db=CONFIG['cache.redis.db'])
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 7b50fdf0..9f92e8e1 100644
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -2,28 +2,37 @@
 
 # 1) start server:
 #   without caching:
-#       REDIS_HOST=None CHEATSH_PORT=50000 python bin/srv.py
+#       CHEATSH_CACHE_TYPE=none CHEATSH_PORT=50000 python bin/srv.py
 #       (recommended)
 #   with caching:
-#       REDIS_PREFIX=TEST1 CHEATSH_PORT=50000 python bin/srv.py 
+#       CHEATSH_REDIS_PREFIX=TEST1 CHEATSH_PORT=50000 python bin/srv.py
 #       (for complex search queries + to test caching)
 # 2) configure CHTSH_URL
 # 3) run the script
 
+# work from script's dir
+cd "$(dirname "$0")" || exit
+
+# detect Python - if not set in env, try default virtualenv
 PYTHON="${PYTHON:-../ve/bin/python}"
-"$PYTHON" --version 2>&1 | grep -q 'Python 2' && python_version=2 || python_version=3
+# if no virtalenv, try current python3 binary
+if ! command -v "$PYTHON" &> /dev/null; then
+  PYTHON=$(command -v python3)
+fi
+python_version="$($PYTHON -c 'import sys; print(sys.version_info[0])')"
+echo "Using PYTHON $python_version: $PYTHON"
 
 skip_online="${CHEATSH_TEST_SKIP_ONLINE:-NO}"
 test_standalone="${CHEATSH_TEST_STANDALONE:-YES}"
 show_details="${CHEATSH_TEST_SHOW_DETAILS:-YES}"
 update_tests_results="${CHEATSH_UPDATE_TESTS_RESULTS:-NO}"
+CHTSH_URL="${CHTSH_URL:-http://localhost:8002}"
 
 TMP=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)
 TMP2=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)
 TMP3=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX)
 trap 'rm -rf $TMP $TMP2 $TMP3' EXIT
 
-export CHTSH_URL=http://cht.sh:50000
 CHTSH_SCRIPT=$(dirname "$(dirname "$(readlink -f "$0")")")/share/cht.sh.txt
 
 export PYTHONIOENCODING=UTF-8
@@ -40,6 +49,7 @@ failed=0
 
 
 while read -r number test_line; do
+  echo -e "\e[34mRunning $number: \e[36m$test_line\e[0m"
   if [ "$skip_online" = YES ]; then
     if [[ $test_line = *\[online\]* ]]; then
       echo "$number is [online]; skipping"
@@ -48,10 +58,12 @@ while read -r number test_line; do
   fi
 
   if [[ "$python_version" = 2 ]] && [[ $test_line = *\[python3\]* ]]; then
+    echo "$number is for Python 3; skipping"
     continue
   fi
 
   if [[ "$python_version" = 3 ]] && [[ $test_line = *\[python2\]* ]]; then
+    echo "$number is for Python 2; skipping"
     continue
   fi
 
@@ -60,20 +72,25 @@ while read -r number test_line; do
 
   if [ "$test_standalone" = YES ]; then
     test_line="${test_line//cht.sh /}"
-    "${PYTHON}" ../lib/standalone.py "$test_line" > "$TMP" 2> /dev/null
+    [[ $show_details == YES ]] && echo "${PYTHON} ../lib/standalone.py $test_line"
+    "${PYTHON}" ../lib/standalone.py "$test_line" > "$TMP"
   elif [[ $test_line = "cht.sh "* ]]; then
     test_line="${test_line//cht.sh /}"
+    [[ $show_details == YES ]] && echo "bash $CHTSH_SCRIPT $test_line"
     eval "bash $CHTSH_SCRIPT $test_line" > "$TMP"
   else
+    [[ $show_details == YES ]] && echo "curl -s $CHTSH_URL/$test_line"
     eval "curl -s $CHTSH_URL/$test_line" > "$TMP"
   fi
 
-  if ! diff results/"$number" "$TMP" > "$TMP2"; then
+  if ! diff -u3 --color=always results/"$number" "$TMP" > "$TMP2"; then
     if [[ $CHEATSH_UPDATE_TESTS_RESULTS = NO ]]; then
       if [ "$show_details" = YES ]; then
-        echo "$ CHEATSH_CACHE_TYPE=none python ../lib/standalone.py $test_line"
         cat "$TMP2"
       fi
+      if grep -q "Internal Server Error" "$TMP2"; then
+        [[ $TRAVIS == true ]] && docker logs chtsh
+      fi
       echo "FAILED: [$number] $test_line"
     else
       cat "$TMP" > results/"$number"

Travis status from my fork https://travis-ci.com/github/abitrolly/cheat.sh/builds

---

They don't really work well.

![image](https://user-images.githubusercontent.com/8781107/88830555-ca921800-d1d6-11ea-9a8c-77b9201c63fe.png)
