From: Philipp Holzer <admin+github@philipp.info>
Date: Mon, 16 Sep 2019 12:47:49 +0000 (+0200)
Subject: Add Drone CI
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=d5dd12b8f8bc7d08813fee3e22831daf45c9052d;p=friendica.git

Add Drone CI
- Add drone test environment
- Add drone config
- apt phpunit
- Fix api.php
- Fix item.php
- Fix DBStructure
- Check if caching is possible during tests
---

diff --git a/.drone.yml b/.drone.yml
new file mode 100644
index 0000000000..0d826cf694
--- /dev/null
+++ b/.drone.yml
@@ -0,0 +1,34 @@
+kind: pipeline
+name: mysql-php7.1
+
+steps:
+- name: mysql-php7.1
+  image: friendicaci/php7.1:php7.1
+  commands:
+    - NOCOVERAGE=true ./autotest.sh
+  environment:
+    MYSQL_USERNAME: friendica
+    MYSQL_PASSWORD: friendica
+    MYSQL_DATABASE: friendica
+    MYSQL_HOST: mysql
+
+services:
+- name: mysql
+  image: mysql:8.0
+  command: [ "--default-authentication-plugin=mysql_native_password" ]
+  environment:
+    MYSQL_ROOT_PASSWORD: friendica
+    MYSQL_USER: friendica
+    MYSQL_PASSWORD: friendica
+    MYSQL_DATABASE: friendica
+  tmpfs:
+    - /var/lib/mysql
+
+#trigger:
+#  branch:
+#    - master
+#    - develop
+#    - "*-rc"
+#  event:
+#    - pull_request
+#    - push
diff --git a/.travis.yml b/.travis.yml
index e2aa84f5c8..493ba652e3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,4 +26,6 @@ before_script:
  - phpenv config-add .travis/redis.ini
  - phpenv config-add .travis/memcached.ini
 
+script: vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover clover.xml
+
 after_success: bash <(curl -s https://codecov.io/bash)
diff --git a/autotest.sh b/autotest.sh
new file mode 100755
index 0000000000..796572d809
--- /dev/null
+++ b/autotest.sh
@@ -0,0 +1,161 @@
+#!/usr/bin/env bash
+
+DATABASENAME=${MYSQL_DATABASE:-test}
+DATABASEUSER=${MYSQL_USERNAME:-friendica}
+DATABASEHOST=${MYSQL_HOST:-localhost}
+BASEDIR=$PWD
+
+export MYSQL_DATABASE="$DATABASENAME"
+export MYSQL_USERNAME="$DATABASEUSER"
+export MYSQL_PASSWORD="friendica"
+
+if [ -z "$PHP_EXE" ]; then
+  PHP_EXE=php
+fi
+PHP=$(which "$PHP_EXE")
+# Use the Friendica internal composer
+COMPOSER="$BASEDIR/bin/composer.phar"
+
+set -e
+
+_XDEBUG_CONFIG=$XDEBUG_CONFIG
+unset XDEBUG_CONFIG
+
+if [ -x "$PHP" ]; then
+  echo "Using PHP executable $PHP"
+else
+  echo "Could not find PHP executable $PHP_EXE" >&2
+  exit 3
+fi
+
+echo "Installing depdendencies"
+$PHP "$COMPOSER" install
+
+PHPUNIT="$BASEDIR/vendor/bin/phpunit"
+
+if [ -x "$PHPUNIT" ]; then
+  echo "Using PHPUnit executable $PHPUNIT"
+else
+  echo "Could not find PHPUnit executable after composer $PHPUNIT" >&2
+  exit 3
+fi
+
+if ! [ \( -w config -a ! -f config/local.config.php \) -o \( -f config/local.config.php -a -w config/local.config.php \) ]; then
+	echo "Please enable write permissions on config and config/config.php" >&2
+	exit 1
+fi
+
+# Back up existing (dev) config if one exists and backup not already there
+if [ -f config/local.config.php ] && [ ! -f config/local.config-autotest-backup.php ]; then
+  mv config/local.config.php config/local.config-autotest-backup.php
+fi
+
+function cleanup_config {
+
+    if [ -n "$DOCKER_CONTAINER_ID" ]; then
+      echo "Kill the docker $DOCKER_CONTAINER_ID"
+      docker stop "$DOCKER_CONTAINER_ID"
+      docker rm -f "$DOCKER_CONTAINER_ID"
+    fi
+
+    cd "$BASEDIR"
+
+    # Restore existing config
+    if [ -f config/local.config-autotest-backup.php ]; then
+      mv config/local.config-autotest-backup.php config/local.config.php
+    fi
+}
+
+# restore config on exit
+trap cleanup_config EXIT
+
+function execute_tests {
+    echo "Setup environment for MariaDB testing ..."
+    # back to root folder
+    cd "$BASEDIR"
+
+    # backup current config
+    if [ -f config/local.config.php ]; then
+      mv config/local.config.php config/local.config-autotest-backup.php
+    fi
+
+    if [ -n "$USEDOCKER" ]; then
+      echo "Fire up the mysql docker"
+      DOCKER_CONTAINER_ID=$(docker run \
+              -e MYSQL_ROOT_PASSWORD=friendica \
+              -e MYSQL_USER="$DATABASEUSER" \
+              -e MYSQL_PASSWORD=friendica \
+              -e MYSQL_DATABASE="$DATABASENAME" \
+              -d mysql)
+      DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
+    else
+      if [ -z "$DRONE" ]; then  # no need to drop the DB when we are on CI
+        if [ "mysql" != "$(mysql --version | grep -o mysql)" ]; then
+          echo "Your mysql binary is not provided by mysql"
+          echo "To use the docker container set the USEDOCKER environment variable"
+          exit 3
+        fi
+        mysql -u "$DATABASEUSER" -pfriendica -e "DROP DATABASE IF EXISTS $DATABASENAME"
+        mysql -u "$DATABASEUSER" -pfriendica -e "CREATE DATABASE $DATABASENAME DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"
+      else
+        DATABASEHOST=mysql
+      fi
+    fi
+
+    echo "Waiting for MySQL $DATABASEHOST initialization..."
+    if ! bin/wait-for-connection $DATABASEHOST 3306 300; then
+      echo "[ERROR] Waited 300 seconds, no response" >&2
+      exit 1
+    fi
+
+    if [ -n "$USEDOCKER" ]; then
+      echo "Initialize database..."
+      docker exec $DOCKER_CONTAINER_ID mysql -u root -pfriendica -e 'CREATE DATABASE IF NOT EXISTS $DATABASENAME;'
+    fi
+
+    export MYSQL_HOST="$DATABASEHOST"
+
+    #call installer
+    echo "Installing Friendica..."
+    "$PHP" ./bin/console.php autoinstall --dbuser="$DATABASEUSER" --dbpass=friendica --dbdata="$DATABASENAME" --dbhost="$DATABASEHOST" --url=https://friendica.local --admin=admin@friendica.local
+
+    #test execution
+    echo "Testing..."
+    rm -fr "coverage-html"
+    mkdir "coverage-html"
+    if [[ "$_XDEBUG_CONFIG" ]]; then
+      export XDEBUG_CONFIG=$_XDEBUG_CONFIG
+    fi
+
+    COVER=''
+    if [ -z "$NOCOVERAGE" ]; then
+      COVER="--coverage-clover autotest-clover.xml --coverage-html coverage-html"
+    else
+      echo "No coverage"
+    fi
+
+    INPUT="$BASEDIR/tests"
+    if [ -n "$1" ]; then
+      INPUT="$INPUT/$1"
+    fi
+
+    echo "${PHPUNIT[@]}" --configuration tests/phpunit.xml $COVER --log-junit "autotest-results.xml" "$INPUT" "$2"
+    "${PHPUNIT[@]}" --configuration tests/phpunit.xml $COVER --log-junit "autotest-results.xml" "$INPUT" "$2"
+    RESULT=$?
+
+    if [ -n "$DOCKER_CONTAINER_ID" ]; then
+      echo "Kill the docker $DOCKER_CONTAINER_ID"
+      docker stop $DOCKER_CONTAINER_ID
+      docker rm -f $DOCKER_CONTAINER_ID
+      unset $DOCKER_CONTAINER_ID
+    fi
+}
+
+#
+# Start the test execution
+#
+if [ -n "$1" ] && [ ! -f "tests/$FILENAME" ] && [ "${FILENAME:0:2}" != "--" ]; then
+  execute_tests "$FILENAME" "$2"
+else
+  execute_tests
+fi
diff --git a/bin/wait-for-connection b/bin/wait-for-connection
new file mode 100755
index 0000000000..67990f9f93
--- /dev/null
+++ b/bin/wait-for-connection
@@ -0,0 +1,40 @@
+#!/usr/bin/php
+
+<?php
+$timeout = 60;
+switch ($argc) {
+	case 4:
+		$timeout = (float)$argv[3];
+	case 3:
+		$host = $argv[1];
+		$port = (int)$argv[2];
+		break;
+	default:
+		fwrite(STDERR, 'Usage: '.$argv[0].' host port [timeout]'."\n");
+		exit(2);
+}
+if ($timeout < 0) {
+	fwrite(STDERR, 'Timeout must be greater than zero'."\n");
+	exit(2);
+}
+if ($port < 1) {
+	fwrite(STDERR, 'Port must be an integer greater than zero'."\n");
+	exit(2);
+}
+$socketTimeout = (float)ini_get('default_socket_timeout');
+if ($socketTimeout > $timeout) {
+	$socketTimeout = $timeout;
+}
+$stopTime = time() + $timeout;
+do {
+	$sock = @fsockopen($host, $port, $errno, $errstr, $socketTimeout);
+	if ($sock !== false) {
+		fclose($sock);
+		fwrite(STDOUT, "\n");
+		exit(0);
+	}
+	sleep(1);
+	fwrite(STDOUT, '.');
+} while (time() < $stopTime);
+fwrite(STDOUT, "\n");
+exit(1);
\ No newline at end of file
diff --git a/include/api.php b/include/api.php
index bdab20b75a..8b938508bd 100644
--- a/include/api.php
+++ b/include/api.php
@@ -48,9 +48,9 @@ use Friendica\Util\Proxy as ProxyUtils;
 use Friendica\Util\Strings;
 use Friendica\Util\XML;
 
-require_once 'mod/share.php';
-require_once 'mod/item.php';
-require_once 'mod/wall_upload.php';
+require_once __DIR__ . '/../mod/share.php';
+require_once __DIR__ . '/../mod/item.php';
+require_once __DIR__ . '/../mod/wall_upload.php';
 
 define('API_METHOD_ANY', '*');
 define('API_METHOD_GET', 'GET');
diff --git a/mod/api.php b/mod/api.php
index 4a1db1be55..9a802b515a 100644
--- a/mod/api.php
+++ b/mod/api.php
@@ -2,6 +2,7 @@
 /**
  * @file mod/api.php
  */
+
 use Friendica\App;
 use Friendica\Core\Config;
 use Friendica\Core\L10n;
@@ -9,7 +10,7 @@ use Friendica\Core\Renderer;
 use Friendica\Database\DBA;
 use Friendica\Module\Login;
 
-require_once 'include/api.php';
+require_once __DIR__ . '/../include/api.php';
 
 function oauth_get_client(OAuthRequest $request)
 {
diff --git a/mod/item.php b/mod/item.php
index 8bc394bcb9..2ebf5a274b 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -42,7 +42,7 @@ use Friendica\Util\Security;
 use Friendica\Util\Strings;
 use Friendica\Worker\Delivery;
 
-require_once 'include/items.php';
+require_once __DIR__ . '/../include/items.php';
 
 function item_post(App $a) {
 	if (!local_user() && !remote_user()) {
diff --git a/phpunit.xml b/phpunit.xml
deleted file mode 100644
index a46f7be7b9..0000000000
--- a/phpunit.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0"?>
-<phpunit
-	bootstrap="tests/bootstrap.php"
-	verbose="true">
-    <testsuites>
-        <testsuite>
-            <directory>tests/</directory>
-        </testsuite>
-    </testsuites>
-	<!-- Filters for Code Coverage -->
-	<filter>
-		<whitelist>
-			<directory suffix=".php">.</directory>
-			<exclude>
-				<directory suffix=".php">config/</directory>
-				<directory suffix=".php">doc/</directory>
-				<directory suffix=".php">images/</directory>
-				<directory suffix=".php">library/</directory>
-				<directory suffix=".php">spec/</directory>
-				<directory suffix=".php">tests/</directory>
-				<directory suffix=".php">view/</directory>
-			</exclude>
-		</whitelist>
-	</filter>
-	<logging>
-		<log type="coverage-clover" target="clover.xml" />
-	</logging>
-	<listeners>
-		<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
-	</listeners>
-</phpunit>
diff --git a/src/Core/Cache/MemcacheCache.php b/src/Core/Cache/MemcacheCache.php
index 7171669520..53a6523f56 100644
--- a/src/Core/Cache/MemcacheCache.php
+++ b/src/Core/Cache/MemcacheCache.php
@@ -37,7 +37,7 @@ class MemcacheCache extends Cache implements IMemoryCache
 		$memcache_host = $config->get('system', 'memcache_host');
 		$memcache_port = $config->get('system', 'memcache_port');
 
-		if (!$this->memcache->connect($memcache_host, $memcache_port)) {
+		if (!@$this->memcache->connect($memcache_host, $memcache_port)) {
 			throw new Exception('Expected Memcache server at ' . $memcache_host . ':' . $memcache_port . ' isn\'t available');
 		}
 	}
diff --git a/src/Core/Cache/RedisCache.php b/src/Core/Cache/RedisCache.php
index b2638c49f3..3558a38464 100644
--- a/src/Core/Cache/RedisCache.php
+++ b/src/Core/Cache/RedisCache.php
@@ -37,9 +37,9 @@ class RedisCache extends Cache implements IMemoryCache
 		$redis_pw   = $config->get('system', 'redis_password');
 		$redis_db   = $config->get('system', 'redis_db', 0);
 
-		if (isset($redis_port) && !$this->redis->connect($redis_host, $redis_port)) {
+		if (isset($redis_port) && !@$this->redis->connect($redis_host, $redis_port)) {
 			throw new Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
-		} elseif (!$this->redis->connect($redis_host)) {
+		} elseif (!@$this->redis->connect($redis_host)) {
 			throw new Exception('Expected Redis server at ' . $redis_host . ' isn\'t available');
 		}
 
diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php
index cf707f2055..72b903e076 100644
--- a/src/Database/DBStructure.php
+++ b/src/Database/DBStructure.php
@@ -12,7 +12,7 @@ use Friendica\Core\L10n;
 use Friendica\Core\Logger;
 use Friendica\Util\DateTimeFormat;
 
-require_once 'include/dba.php';
+require_once __DIR__ . '/../../include/dba.php';
 
 /**
  * @brief This class contain functions for the database management
diff --git a/src/Database/Database.php b/src/Database/Database.php
index 813d4e9853..6b4b621d37 100644
--- a/src/Database/Database.php
+++ b/src/Database/Database.php
@@ -67,7 +67,7 @@ class Database
 	{
 		// Use environment variables for mysql if they are set beforehand
 		if (!empty($server['MYSQL_HOST'])
-		    && !empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER']))
+		    && (!empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER'])))
 		    && $server['MYSQL_PASSWORD'] !== false
 		    && !empty($server['MYSQL_DATABASE']))
 		{
diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php
index e4ea1122f0..128ecc88c7 100644
--- a/tests/Util/Database/StaticDatabase.php
+++ b/tests/Util/Database/StaticDatabase.php
@@ -80,7 +80,7 @@ class StaticDatabase extends Database
 	{
 		// Use environment variables for mysql if they are set beforehand
 		if (!empty($server['MYSQL_HOST'])
-		    && !empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER']))
+		    && (!empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER'])))
 		    && $server['MYSQL_PASSWORD'] !== false
 		    && !empty($server['MYSQL_DATABASE']))
 		{
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
new file mode 100644
index 0000000000..73b643e13a
--- /dev/null
+++ b/tests/phpunit.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<phpunit
+	bootstrap="bootstrap.php"
+	verbose="true">
+	<testsuite name='friendica'>
+		<directory suffix='.php'>functional/</directory>
+		<directory suffix='.php'>include/</directory>
+		<directory suffix='.php'>src/</directory>
+		<directory suffix='.php'>./</directory>
+	</testsuite>
+	<!-- Filters for Code Coverage -->
+	<filter>
+		<whitelist>
+			<directory suffix=".php">..</directory>
+			<exclude>
+				<directory suffix=".php">config/</directory>
+				<directory suffix=".php">doc/</directory>
+				<directory suffix=".php">images/</directory>
+				<directory suffix=".php">library/</directory>
+				<directory suffix=".php">spec/</directory>
+				<directory suffix=".php">tests/</directory>
+				<directory suffix=".php">view/</directory>
+			</exclude>
+		</whitelist>
+	</filter>
+	<listeners>
+		<listener class="JohnKary\PHPUnit\Listener\SpeedTrapListener" />
+	</listeners>
+</phpunit>
diff --git a/tests/src/Core/Cache/MemcacheCacheTest.php b/tests/src/Core/Cache/MemcacheCacheTest.php
index ccc3723153..8abf169aea 100644
--- a/tests/src/Core/Cache/MemcacheCacheTest.php
+++ b/tests/src/Core/Cache/MemcacheCacheTest.php
@@ -14,16 +14,22 @@ class MemcacheCacheTest extends MemoryCacheTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['MEMCACHE_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcache_host')
-			->andReturn('localhost');
+			->andReturn($host);
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcache_port')
 			->andReturn(11211);
 
-		$this->cache = new MemcacheCache('localhost', $configMock);
+		try {
+			$this->cache = new MemcacheCache($host, $configMock);
+		} catch (\Exception $e) {
+			$this->markTestSkipped('Memcache is not available');
+		}
 		return $this->cache;
 	}
 
diff --git a/tests/src/Core/Cache/MemcachedCacheTest.php b/tests/src/Core/Cache/MemcachedCacheTest.php
index d887250197..c8c65c9caa 100644
--- a/tests/src/Core/Cache/MemcachedCacheTest.php
+++ b/tests/src/Core/Cache/MemcachedCacheTest.php
@@ -16,14 +16,20 @@ class MemcachedCacheTest extends MemoryCacheTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['MEMCACHED_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcached_hosts')
-			->andReturn([0 => 'localhost, 11211']);
+			->andReturn([0 => $host . ', 11211']);
 
 		$logger = new NullLogger();
 
-		$this->cache = new MemcachedCache('localhost', $configMock, $logger);
+		try {
+			$this->cache = new MemcachedCache($host, $configMock, $logger);
+		} catch (\Exception $exception) {
+			$this->markTestSkipped('Memcached is not available');
+		}
 		return $this->cache;
 	}
 
diff --git a/tests/src/Core/Cache/RedisCacheTest.php b/tests/src/Core/Cache/RedisCacheTest.php
index df353252df..cddefe3acc 100644
--- a/tests/src/Core/Cache/RedisCacheTest.php
+++ b/tests/src/Core/Cache/RedisCacheTest.php
@@ -15,10 +15,12 @@ class RedisCacheTest extends MemoryCacheTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['REDIS_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'redis_host')
-			->andReturn('localhost');
+			->andReturn($host);
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'redis_port')
@@ -33,7 +35,11 @@ class RedisCacheTest extends MemoryCacheTest
 			->with('system', 'redis_password')
 			->andReturn(null);
 
-		$this->cache = new RedisCache('localhost', $configMock);
+		try {
+			$this->cache = new RedisCache($host, $configMock);
+		} catch (\Exception $e) {
+			$this->markTestSkipped('Redis is not available.');
+		}
 		return $this->cache;
 	}
 
diff --git a/tests/src/Core/Lock/MemcacheCacheLockTest.php b/tests/src/Core/Lock/MemcacheCacheLockTest.php
index f550ac51a6..4e7dd30340 100644
--- a/tests/src/Core/Lock/MemcacheCacheLockTest.php
+++ b/tests/src/Core/Lock/MemcacheCacheLockTest.php
@@ -16,15 +16,26 @@ class MemcacheCacheLockTest extends LockTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['MEMCACHE_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcache_host')
-			->andReturn('localhost');
+			->andReturn($host);
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcache_port')
 			->andReturn(11211);
 
-		return new CacheLock(new MemcacheCache('localhost', $configMock));
+		$lock = null;
+
+		try {
+			$cache = new MemcacheCache($host, $configMock);
+			$lock = new CacheLock($cache);
+		} catch (\Exception $e) {
+			$this->markTestSkipped('Memcache is not available');
+		}
+
+		return $lock;
 	}
 }
diff --git a/tests/src/Core/Lock/MemcachedCacheLockTest.php b/tests/src/Core/Lock/MemcachedCacheLockTest.php
index 8b59f91bb7..2249b88b8c 100644
--- a/tests/src/Core/Lock/MemcachedCacheLockTest.php
+++ b/tests/src/Core/Lock/MemcachedCacheLockTest.php
@@ -17,13 +17,24 @@ class MemcachedCacheLockTest extends LockTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['MEMCACHED_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'memcached_hosts')
-			->andReturn([0 => 'localhost, 11211']);
+			->andReturn([0 => $host . ', 11211']);
 
 		$logger = new NullLogger();
 
-		return new CacheLock(new MemcachedCache('localhost', $configMock, $logger));
+		$lock = null;
+
+		try {
+			$cache = new MemcachedCache($host, $configMock, $logger);
+			$lock = new CacheLock($cache);
+		} catch (\Exception $e) {
+			$this->markTestSkipped('Memcached is not available');
+		}
+
+		return $lock;
 	}
 }
diff --git a/tests/src/Core/Lock/RedisCacheLockTest.php b/tests/src/Core/Lock/RedisCacheLockTest.php
index 0ebc02160e..5cecd8f4c1 100644
--- a/tests/src/Core/Lock/RedisCacheLockTest.php
+++ b/tests/src/Core/Lock/RedisCacheLockTest.php
@@ -16,10 +16,12 @@ class RedisCacheLockTest extends LockTest
 	{
 		$configMock = \Mockery::mock(Configuration::class);
 
+		$host = $_SERVER['REDIS_HOST'] ?? 'localhost';
+
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'redis_host')
-			->andReturn('localhost');
+			->andReturn($host);
 		$configMock
 			->shouldReceive('get')
 			->with('system', 'redis_port')
@@ -34,6 +36,15 @@ class RedisCacheLockTest extends LockTest
 			->with('system', 'redis_password')
 			->andReturn(null);
 
-		return new CacheLock(new RedisCache('localhost', $configMock));
+		$lock = null;
+
+		try {
+			$cache = new RedisCache($host, $configMock);
+			$lock = new CacheLock($cache);
+		} catch (\Exception $e) {
+			$this->markTestSkipped('Redis is not available');
+		}
+
+		return $lock;
 	}
 }