Переглянути джерело

[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.
Daniele Alessandri 10 роки тому
батько
коміт
1da827c0ae

+ 87 - 20
tests/PHPUnit/PredisTestCase.php

@@ -20,6 +20,8 @@ use Predis\Profile\ServerProfileInterface;
  */
 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.
@@ -164,13 +166,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());
 
@@ -184,6 +190,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;")) {
@@ -212,29 +232,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.
      */
-    public function markTestSkippedOnRedisVersionBelow($expectedVersion, $message = '', $remote = true)
+    protected function sleep($seconds)
     {
-        $callback = function ($test, $version) use ($message, $expectedVersion) {
-            $test->markTestSkipped($message ?: "Test requires Redis $expectedVersion, current is $version.");
-        };
+        usleep($seconds * 1000000);
+    }
 
-        $method = $remote ? 'executeOnRedisVersion' : 'executeOnProfileVersion';
-        $this->$method($expectedVersion, '<', $callback);
+    /**
+     *
+     */
+    protected function setRequiredRedisVersionFromAnnotation()
+    {
+        $annotations = $this->getAnnotations();
+
+        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\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\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\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\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\ServerException
+     * @requiresRedisVersion >= 2.6.9
      * @dataProvider invalidConnectionNameProvider
+     * @expectedException Predis\ServerException
      */
     public function testInvalidSetNameOfConnection($invalidConnectionName)
     {
-         $this->markTestSkippedOnRedisVersionBelow('2.6.9');
-
          $redis = $this->getClient();
          $redis->client('SETNAME', $invalidConnectionName);
     }

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

@@ -82,11 +82,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');
@@ -99,11 +98,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');
@@ -116,11 +114,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');
@@ -131,13 +128,12 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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');
@@ -146,13 +142,12 @@ class ZSetLexCountTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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

@@ -109,11 +109,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');
@@ -126,11 +125,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');
@@ -145,11 +143,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');
@@ -164,11 +161,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');
@@ -182,11 +178,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');
@@ -200,13 +195,12 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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');
@@ -215,13 +209,12 @@ class ZSetRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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

@@ -82,11 +82,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');
@@ -99,11 +98,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');
@@ -114,11 +112,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');
@@ -129,11 +126,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');
@@ -144,13 +140,12 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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');
@@ -159,13 +154,12 @@ class ZSetRemoveRangeByLexTest extends PredisCommandTestCase
 
     /**
      * @group connected
+     * @requiresRedisVersion >= 2.8.9
      * @expectedException Predis\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');