Официальный выпуск PHPUnit 3.5 теперь доступен для установки PEAR после длительного периода бета-тестирования. PHPUnit 3.5 предоставляет много новых функций, таких как куча новых методов утверждений и аннотаций, и небольшой, но очень полезный мой вклад: MockBuilder.компонентизация
База кода PHPUnit была разделена на несколько компонентов, которые связаны друг с другом через зависимости пакета PEAR. Если при обновлении до PHPUnit 3.5 у вас возникли проблемы, новая установка должна исправить их и загрузить все необходимые пакеты:
sudo pear uninstall phpunit/PHPUnit sudo pear install phpunit/PHPUnit
Я также натолкнулся на некоторые недостающие каналы, с которых PHPUnit захватывает пакеты:
sudo pear channel-discover pear.symfony-project.com sudo pear channel-discover components.ez.no
Я всегда предпочитаю устанавливать pear (и, следовательно, pecl) через менеджер пакетов Ubuntu, а затем оставить двоичный пакет pear для управления всеми пакетами PHP, такими как PHPUnit и Phing. Таким образом, быстрые обновления обычно доступны, и вы не заканчиваете тем, что смешиваете дабы Ubuntu с загруженными пакетами, просто применяя единственное средство установки. То же самое можно сделать и для других дистрибутивов Linux.
Кстати, компонентизация не влияет на обычного пользователя (только участников, которые должны работать в разных репозиториях git), а также на ваши тесты. Как и следовало ожидать от вспомогательного выпуска, API PHPUnit 3.x расширяется только новыми функциями, но поддерживается обратной совместимостью.
Новые утверждения и аннотации
Введены некоторые удобные новые методы утверждений, и я приведу практический пример позже в этом посте. Вызов этих методов вместо создания пользовательских логических условий для передачи в assertTrue () означает удаление сообщений об ошибках без добавления дополнительного
аргумента утверждения $ message и улучшенную читаемость тестов. Вы можете легко извлекать пользовательские утверждения в их собственные методы, но наличие их в базовом классе тестового примера делает его доступным везде и везде.
MockBuilder
Наконец, я хотел бы поговорить о моем небольшом дополнении к PHPUnit mocking Api, которое является реализацией шаблона Builder для фиктивных объектов (необъяснимо опущено из журнала изменений, опубликованного на Github).
Как вы, возможно, знаете, Api 3.4 содержит метод getMock () с 7 аргументами. Поскольку некоторые из этих аргументов являются логическими значениями, вызов getMock () может стать очень неясным, если вы не запомните значение всех 7 аргументов. К счастью, большинство из них являются необязательными, но для указания одного из последних аргументов, которые вы должны включить, и постарайтесь найти правильное значение по умолчанию, которое меняется в зависимости от типа параметра. Это приводит к классическому вызову для получения макета с переопределенным конструктором:
$this->getMock('My_Class', array(), array(), '', false);
Который может даже добраться до:
$this->getMock('My_Class', array(), array(), '', false, false, false);
Или, если вы действительно хотите указать дополнительное поведение, чтобы:
$this->getMock('My_Class', array('doSomething', 'doSomethingElse'), array('someParam', 42), '', true, false);
Шаблон создания Builder — это небольшой уровень абстракции над процессом создания экземпляра, который в данном случае дает вам четкий API-интерфейс:
$this->getMockBuilder('My_Class')
->disableOriginalConstructor()
->getMock();
Я надеюсь, что этот синтаксический сахар поможет вам очистить ваш набор тестов, который должен иметь те же права и внимание, что и ваш рабочий код.
Примеры
Я написал пример тестового примера, в котором используются новые функции PHPUnit 3.5, чтобы вы могли быстро понять API и сохранить его в качестве справочного материала для обновления своего набора тестов.
<?php
class NewFunctionalities extends PHPUnit_Framework_TestCase
{
/**
* Some quick assertions on variables.
*/
public function testNewAssertions()
{
$this->assertEmpty(null);
$this->assertEmpty(0);
$this->assertNotEmpty(42);
}
/**
* Some more sophisticated assertions on objects fields.
*/
public function testNewAssertionsOnObjectsAttributes()
{
$car = new Car;
$this->assertAttributeEmpty('wheels', $car);
$car->wheels = 4;
$this->assertAttributeNotEmpty('wheels', $car);
}
/**
* If you have ever written $this->assertTrue($object instanceof My_Class),
* you'll appreciate this.
* I only wish PHP allowed classes and interfaces to be passed like in Java:
* $this->assertInstanceOf(Countable.class, $car)
* to catch undefined classes issues.
*/
public function testNewAssertionsOnObjects()
{
$car = new Car();
$this->assertInstanceOf('Car', $car);
$this->assertNotInstanceOf('Countable', $car);
}
/**
* Simplified type checks.
*/
public function testNewAssertionsOnScalars()
{
$string = 'ElePHPants are cute';
$this->assertInternalType('string', $string);
$this->assertNotInternalType('int', $string);
}
/**
* Builder pattern for mocks.
* Other methods on MockBuilder: setConstructorArgs(), setMockClassName(),
* disableOriginalClone(), disableAutoload()
*/
public function testMockBuilder()
{
$busMock = $this->getMockBuilder('Bus')
->setMethods(array('brake', 'steer'))
->disableOriginalConstructor()
->getMock();
$this->assertInstanceOf('Bus', $busMock);
}
/**
* Annotations to expand declarative exception checking.
* Error conditions are usually a neglected part of test cases.
*
* @expectedException CustomException
* @expectedExceptionMessage Trying out new features
* @expectedExceptionCode 42
*/
public function testExceptions()
{
throw new CustomException("Trying out new features", 42);
}
}
class Car
{
public $wheels;
public function brake() {}
public function steer($direction) {}
}
class Bus
{
private $_driver;
public function __construct(Driver $driver)
{
$this->_driver = $driver;
}
public function brake() {}
public function steer($direction) {}
}
class CustomException extends Exception {}