mercredi 4 mai 2016

Optimizing unit tests which testing same methods with different parameters

I have lots of PHP classes like this:

class Article
{
    public function fetchAll($params) {
        if ($params["client"] == "mobile") {
            return [
                "author" => "",
                "body" => ""
            ];
        }
        return [
            "author" => "",
            "body" => "",
            "publishedOn => """
        ];
    }
}

As you see fetchAll() method returning different fields according to $params["client"]. I need to check existence of these fields. I have 3 options to achieve my goal.

(Note: All codes simplified, dont worry about syntax errors.)

Method 1 : Different test methods for different clients

class ArticleTest extends ...
{
    public function testFetchAll() {
        $params = [];
        $data = $article->fetchAll($params);
        $this->assertEqual(array_keys($data), ["author","body","publishedOn"]);
    }
    public function testFetchAll2() {
        $params = ["client" => "mobile"];
        $data = $article->fetchAll($params);
        $this->assertEqual(array_keys($data), ["author","body"]);
    }
}

Cons: Using same codes again and again, it's a really bad practice. No need to explain. Refactoring is really difficult. Also this method will cause dozens of test methods.

Method 2 : Using for-loop for different clients

class ArticleTest extends ...
{
    public function testFetchAll() {
        for ($i=0; $i<2; $i++) {
            $params = [];
            if ($i == 1) $params["client"] = "mobile";
            $data = $article->fetchAll($params);
            if ($i == 0)
                $this->assertEqual(array_keys($data), ["author","body","publishedOn"]);
            else
                $this->assertEqual(array_keys($data), ["author","body"]);
        }
    }
}

Cons : I'm not sure if using loops on PHPUnit tests is a good idea. Also code readability decreased.

Method 3 : Different test cases / test files for different clients

// articleTest.php
class ArticleTest extends ...
{
    public function testFetchAll() {
        $params = [];
        $data = $article->fetchAll($params);
        $this->assertEqual(array_keys($data), ["author","body","publishedOn"]);
    }
}
// articleTest2.php
class ArticleTest2 extends ...
{
    public function testFetchAll() {
        $params = ["client" => "mobile"];
        $data = $article->fetchAll($params);
        $this->assertEqual(array_keys($data), ["author","body"]);
    }
}

Cons: This method causing dozens of test files, and using same codes again and again. Refactoring is really difficult.

Performance Comparison

Method 1 : Time: 127 ms, Memory: 8.00Mb

Method 2 : Time: 125 ms, Memory: 8.00Mb

Method 3 : Time: 96 ms, Memory: 8.00Mb

I'm trying to understand which method is better with lots of classes like this and waiting for a discussion about optimizing unit tests in this situation.

Aucun commentaire:

Enregistrer un commentaire