Факер - это один из способов сделать это, но я бы не решился сказать, что это "лучший способ".
Ваши требования:
1. Проверьте набор различных переменных.
2. Эти переменные могут существовать или не существовать в базе данных.
Но у вас есть несколько проблем с тем, как вы разработали этот тест:
- Вы используете
gettype()
и сравниваете его со строкой. Это плохая идея. Если продукт 54 - "foo", и ваш тест возвращает "bar" для 54, он пройдет. Это Программирование по совпадению . Т.е. это работает, но не нарочно.
- То, как вы это настраиваете, на самом деле не решает проблему. Хотя Faker может создавать поддельные данные, он не может автоматически создавать известные хорошие и известные плохие данные для вашей конкретной системы и бизнес-кейсов. Я предполагаю, что вы хотите протестировать известные достоверные данные + ожидаемые результаты, а также известные неверные данные + ожидаемые исключения.
Правильный способ структурировать этот тест - использовать @ dataProvider и фиксации базы данных / тестирование .
Вот как это будет выглядеть:
<?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.
];
}
}
Вот разбивка:
- Использовать пространства имен. Потому что это 2018 год, и это то, что нужно сделать .
- Используйте
use
, чтобы объявить, какие классы вы используете в тесте.
- Используйте
TestCaseTrait
для правильной настройки TestCase
- Закрытая переменная
$pdo
будет содержать подключение к вашей базе данных для вашего класса / теста.
getConnection()
требуется. При этом будут использоваться база данных, имя пользователя и пароль, которые вы настроили в файле phpunit.xml
. Ссылка
getDataSet()
идет и читает ваш источник данных (фикстур), затем усекает вашу базу данных на вашей рабочей станции / dev, импортирует все данные из фикстура, чтобы вывести базу данных в известное состояние. (Обязательно сделайте резервную копию своих данных, прежде чем сделать это. Это специально с потерями. Никогда не выполняйте на производстве).
Далее у вас есть две пары методов для тестовых случаев: тест и поставщик данных.
Поставщик данных в в каждом случае предоставляет идентификатор, который вы хотите проверить, и ожидаемый результат. В случае testProduct
и providerTestProduct
, мы предоставляем ID, что должно существовать в базе данных (как показано в приведенном выше приспособлении). Затем мы можем проверить, что Product::readId()
не только возвращает строку , но на самом деле возвращает правильную строку .
Во втором случае, testProductException()
и providerTestProductException()
, мы преднамеренно отправляем неверные значения в класс, чтобы вызвать исключения, а затем проверяем, чтобы убедиться, что эти неверные значения действительно приводят к желаемому поведению: fail / thrown исключения .