浏览代码

[tests] Use annotations to specify expected Redis server version.

This change targets only method annotations and aims to make the body
of tests more readable using the @requiresRedisVersion annotation.

Tests using this annotation requires to be assigned the "connected"
group of tests because they create a connection to the Redis instance
specified in phpunit.xml to fetch its the version.

This is a quick example of how this annotation can be used:

    /**
     * @group connected
     * @requiresRedisVersion >= 2.8.9
     */
    public function testExecutedOnlyWithMatchingRedisVersion()
    {
    }

Future improvements (currently not needed) include:

  * Same annotation working on a class-level (but still applied only
    to test methods with an explicitly assigned @group connected).

  * Ability to specify a version range.

Meh

Meh
Daniele Alessandri 10 年之前
父节点
当前提交
42f237e306

+ 87 - 20
tests/PHPUnit/PredisTestCase.php

@@ -19,6 +19,8 @@ use Predis\Profile;
  */
 abstract class PredisTestCase extends PHPUnit_Framework_TestCase
 {
+    protected $redisServerVersion = null;
+
     /**
      * Verifies that a Redis command is a valid Predis\Command\CommandInterface
      * instance with the specified ID and command arguments.
@@ -163,13 +165,17 @@ abstract class PredisTestCase extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * @param  string                             $expectedVersion Expected redis version.
-     * @param  string                             $operator        Comparison operator.
-     * @param  callable                           $callback        Callback for matching version.
-     * @throws PHPUnit_Framework_SkippedTestError When expected redis version is not met
+     * Returns the server version of the Redis instance used by the test suite.
+     *
+     * @return string
+     * @throws RuntimeException When the client cannot retrieve the current server version
      */
-    protected function executeOnRedisVersion($expectedVersion, $operator, $callback)
+    protected function getRedisServerVersion()
     {
+        if (isset($this->redisServerVersion)) {
+            return $this->redisServerVersion;
+        }
+
         $client = $this->createClient(null, null, true);
         $info = array_change_key_case($client->info());
 
@@ -183,6 +189,20 @@ abstract class PredisTestCase extends PHPUnit_Framework_TestCase
             throw new RuntimeException('Unable to retrieve server info');
         }
 
+        $this->redisServerVersion = $version;
+
+        return $version;
+    }
+
+    /**
+     * @param  string                             $expectedVersion Expected redis version.
+     * @param  string                             $operator        Comparison operator.
+     * @param  callable                           $callback        Callback for matching version.
+     * @throws PHPUnit_Framework_SkippedTestError When expected redis version is not met
+     */
+    protected function executeOnRedisVersion($expectedVersion, $operator, $callback)
+    {
+        $version = $this->getRedisServerVersion();
         $comparation = version_compare($version, $expectedVersion);
 
         if ($match = eval("return $comparation $operator 0;")) {
@@ -211,29 +231,76 @@ abstract class PredisTestCase extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * @param  string                             $expectedVersion Expected redis version.
-     * @param  string                             $message         Optional message.
-     * @param  bool                               $remote          Based on local profile or remote redis version.
-     * @throws RuntimeException                   When unable to retrieve server info or redis version
-     * @throws PHPUnit_Framework_SkippedTestError When expected redis version is not met
+     * Sleep the test case with microseconds resolution.
+     *
+     * @param float $seconds Seconds to sleep.
+     */
+    protected function sleep($seconds)
+    {
+        usleep($seconds * 1000000);
+    }
+
+    /**
+     *
      */
-    public function markTestSkippedOnRedisVersionBelow($expectedVersion, $message = '', $remote = true)
+    protected function setRequiredRedisVersionFromAnnotation()
     {
-        $callback = function ($test, $version) use ($message, $expectedVersion) {
-            $test->markTestSkipped($message ?: "Test requires Redis $expectedVersion, current is $version.");
-        };
+        $annotations = $this->getAnnotations();
 
-        $method = $remote ? 'executeOnRedisVersion' : 'executeOnProfileVersion';
-        $this->$method($expectedVersion, '<', $callback);
+        if (isset($annotations['method']['requiresRedisVersion'], $annotations['method']['group']) &&
+            !empty($annotations['method']['requiresRedisVersion']) &&
+            in_array('connected', $annotations['method']['group'])
+        ) {
+            $this->required['requiresRedisVersion'] = $annotations['method']['requiresRedisVersion'][0];
+        }
     }
 
     /**
-     * Sleep the test case with microseconds resolution.
      *
-     * @param float $seconds Seconds to sleep.
      */
-    protected function sleep($seconds)
+    protected function checkRequiredRedisVersion()
     {
-        usleep($seconds * 1000000);
+        if (!isset($this->required['requiresRedisVersion'])) {
+            return;
+        }
+
+        $srvVersion = $this->getRedisServerVersion();
+        $expectation = explode(' ', $this->required['requiresRedisVersion'], 2);
+
+        if (count($expectation) === 1) {
+            $expOperator = '>=';
+            $expVersion = $expectation[0];
+        } else {
+            $expOperator = $expectation[0];
+            $expVersion = $expectation[1];
+        }
+
+        $comparation = version_compare($srvVersion, $expVersion);
+
+        if (!$match = eval("return $comparation $expOperator 0;")) {
+            $this->markTestSkipped(
+                "This test requires Redis $expOperator $expVersion but the current version is $srvVersion."
+            );
+        }
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function setRequirementsFromAnnotation()
+    {
+        parent::setRequirementsFromAnnotation();
+
+        $this->setRequiredRedisVersionFromAnnotation();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function checkRequirements()
+    {
+        parent::checkRequirements();
+
+        $this->checkRequiredRedisVersion();
     }
 }

+ 1 - 2
tests/Predis/Command/HyperLogLogAddTest.php

@@ -75,13 +75,12 @@ class HyperLogLogAddTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'HyperLogLog requires Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->lpush('metavars', 'foo', 'hoge');

+ 2 - 4
tests/Predis/Command/HyperLogLogCountTest.php

@@ -76,13 +76,12 @@ class HyperLogLogCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'HyperLogLog requires Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->lpush('metavars', 'foo', 'hoge');
@@ -91,13 +90,12 @@ class HyperLogLogCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongTypeOfAtLeastOneKey()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'HyperLogLog requires Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->pfadd('metavars:1', 'foo', 'hoge');

+ 1 - 2
tests/Predis/Command/HyperLogLogMergeTest.php

@@ -72,13 +72,12 @@ class HyperLogLogMergeTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'HyperLogLog requires Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->pfadd('metavars:1', 'foo', 'hoge');

+ 4 - 7
tests/Predis/Command/ServerClientTest.php

@@ -143,11 +143,10 @@ BUFFER;
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.6.9
      */
     public function testGetsNameOfConnection()
     {
-         $this->markTestSkippedOnRedisVersionBelow('2.6.9');
-
          $redis = $this->getClient();
          $clientName = $redis->client('GETNAME');
          $this->assertNull($clientName);
@@ -159,11 +158,10 @@ BUFFER;
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.6.9
      */
     public function testSetsNameOfConnection()
     {
-         $this->markTestSkippedOnRedisVersionBelow('2.6.9');
-
          $redis = $this->getClient();
 
          $expectedConnectionName = 'foo-baz';
@@ -185,13 +183,12 @@ BUFFER;
 
     /**
      * @group connected
-     * @expectedException Predis\Response\ServerException
+     * @requiresRedisVersion >= 2.6.9
      * @dataProvider invalidConnectionNameProvider
+     * @expectedException Predis\Response\ServerException
      */
     public function testInvalidSetNameOfConnection($invalidConnectionName)
     {
-         $this->markTestSkippedOnRedisVersionBelow('2.6.9');
-
          $redis = $this->getClient();
          $redis->client('SETNAME', $invalidConnectionName);
     }

+ 5 - 10
tests/Predis/Command/ZSetLexCountTest.php

@@ -57,11 +57,10 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testExclusiveIntervalRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -74,11 +73,10 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testInclusiveIntervalRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -91,11 +89,10 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testWholeRangeInterval()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -106,13 +103,12 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage min or max not valid string range item
      */
     public function testThrowsExceptionOnInvalidRangeFormat()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -121,13 +117,12 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->set('foo', 'bar');

+ 7 - 14
tests/Predis/Command/ZSetRangeByLexTest.php

@@ -80,11 +80,10 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testReturnsElementsInWholeRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -97,11 +96,10 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testReturnsElementsInInclusiveRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -116,11 +114,10 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testReturnsElementsInExclusiveRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -135,11 +132,10 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testReturnsElementsInMixedRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -153,11 +149,10 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testRangeWithLimitModifier()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -171,13 +166,12 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage min or max not valid string range item
      */
     public function testThrowsExceptionOnInvalidRangeFormat()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -186,13 +180,12 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->set('foo', 'bar');

+ 6 - 12
tests/Predis/Command/ZSetRemoveRangeByLexTest.php

@@ -57,11 +57,10 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testRemovesRangeByLexWithWholeRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -74,11 +73,10 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testRemovesRangeByLexWithInclusiveRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -89,11 +87,10 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testRemovesRangeByLexWithExclusiveRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -104,11 +101,10 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      */
     public function testRemovesRangeByLexWithMixedRange()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -119,13 +115,12 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage min or max not valid string range item
      */
     public function testThrowsExceptionOnInvalidRangeFormat()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->zadd('letters', 0, 'a', 0, 'b', 0, 'c', 0, 'd', 0, 'e', 0, 'f', 0, 'g');
@@ -134,13 +129,12 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\Response\ServerException
      * @expectedExceptionMessage Operation against a key holding the wrong kind of value
      */
     public function testThrowsExceptionOnWrongType()
     {
-        $this->markTestSkippedOnRedisVersionBelow('2.8.9', 'Lexicographical operations on sorted sets require Redis >= 2.8.9.', true);
-
         $redis = $this->getClient();
 
         $redis->set('foo', 'bar');