компонентизация
База кода 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 {}