PHPUnit如何每次测试不同的变量?

PHPUnit如何每次测试不同的变量?,php,phpunit,Php,Phpunit,我正在编写一个产品类,该类的工作是接收一个产品id,并输出相应的产品name 例如: $Product = new Product; $Product->id = "ff62"; $Product->readId(); echo $Product->name; // returns a string with at least 5 characters. 我的PHPUnit测试方法如下所示: $Product = new Product; $Product->id =

我正在编写一个产品类,该类的工作是接收一个产品
id
,并输出相应的产品
name

例如:

$Product = new Product;
$Product->id = "ff62";
$Product->readId();
echo $Product->name;

// returns a string with at least 5 characters.
我的PHPUnit测试方法如下所示:

$Product = new Product;
$Product->id = "ff62"; // needs to be a variable
$Product->readId();
$this->assertEquals(gettype($Product->name), 'string');
然而,我的目标是每次检查不同的产品ID,而不是检查数据库中可能存在或不存在的
ff62

理想情况下,应能够在测试期间定义
id
变量


测试动态变量的最佳方法是什么?

您可以使用随机数生成将数据集随机化

$value = dechex(random_int(0, 255)).dechex(random_int(0, 255));

$Product = new Product;
$Product->id = $value;
$Product->readId();
$this->assertEquals('string', gettype($Product->name));
$this->assertEquals($value, $Product->name);

人们通常把期望值放在左边,把实际值放在右边。

我发现最好的方法是使用Faker

当我试图测试一个产品的不同实例时,我肯定可以使用Faker随机生成一个产品,并测试是否正确地从数据库中检索该产品

虽然主要用于Laravel、Symfony等,但即使在自定义PHP框架中也很容易使用。

是一种方法,但我不想说它是“最好的方法”

你的要求是: 1.测试一组不同的变量。 2.这些变量可能存在于数据库中,也可能不存在于数据库中

但您在设计此测试时遇到了几个问题:

  • 您正在使用
    gettype()
    并将其与字符串进行比较。这是个坏主意。如果产品54是“foo”,并且您的测试返回54的“bar”,它将通过。这是巧合。也就是说,它是有效的,但不是故意的
  • 你的设置方式并不能真正解决这个问题。虽然Faker可以创建虚假数据,但它无法为您的特定系统和业务案例自动创建已知的好数据和已知的坏数据。我假设您想要测试已知的好数据+预期结果以及已知的坏数据+预期异常 构造此测试的正确方法是使用和

    下面是它的样子:

    <?php
    namespace Foo\Bar;
    
    use PHPUnit\DbUnit\TestCaseTrait;
    use PHPUnit\Framework\TestCase;
    use \PDO;
    USE \Exception;
    
    class ProductTest extends TestCase
    {
        use TestCaseTrait;
    
    
        // only instantiate pdo once for test clean-up/fixture load
        static private $pdo = null;
    
        // only instantiate PHPUnit_Extensions_Database_DB_IDatabaseConnection once per test
        private $conn = null;
    
        final public function getConnection()
        {
            if ($this->conn === null) {
                if (self::$pdo == null) {
                    self::$pdo = new PDO($GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
                }
                $this->conn = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']);
            }
    
            return $this->conn;
        }
    
        public function getDataSet()
        {
            return $this->createMySQLXMLDataSet('tests/unit/testdata/sampleproductdata.xml');
        }
    
        /**
         * Tests products against known good data in the database fixture.
         * @param $id
         * @param $expectedName
         * @dataProvider providerTestProduct
         */
    
        public function testProduct($id, $expectedName) {
            $Product = new Product;
            $Product->id = $id;
            $Product->readId();
            $this->assertSame($expectedName, $Product->name);
        }
    
        /**
         * Provides data that should appear in the database.
         * @return array
         */
        public function providerTestProduct() {
                    // id , expectedName
            return  [ [ "ff62" , "fooproduct"]
                    , [ "dd83" , "barproduct"]
                    , [ "ls98" , "bazproduct"]
                    ];
        }
    
        /**
         * Tests products against known-bad data to ensure proper exceptions are thrown.
         * @param $id
         * @param $expectedName
         */
        public function testProductExceptions($id, $expectedName) {
            $Product = new Product;
            $Product->id = $id;
    
            $this->expectException(Exception::class);
            $Product->readId();
        }
    
        /**
         * Provides test data that when queried against the database should produce an error.
         * @return array
         */
        public function providerTestProductExceptions() {
            // id , expectedName
            return  [ [ "badtype" , "fooproduct"]  //Wrong id type
                    , [ "aaaa" , "barproduct"]     //Does not exist
                    , [ null   , "bazproduct"]     //null is a no-no.
            ];
        }
    }
    

    回波dechex(255)。dechex(98)我原以为你会想要一组固定的产品id,这样你就可以检查你是否希望该项目存在,其他字段应该是什么等@NigelRen你的意思是说最好的做法是针对固定的数据集进行测试。使用秘密API密钥测试API调用如何?我们不能在测试文件中存储API密钥。类似地,本例中的id类似于密钥。我想知道如何对一个可变键进行测试。你想达到什么目的?在单元测试的范围内,测试数据应该是固定的或至少是已知的。API或数据库的外部依赖关系应该被模拟掉,只剩下业务逻辑需要测试。