TDD кто сможет поучить?

  • Автор темы Автор темы craz
  • Дата начала Дата начала
fixxxer
угу, это просто набор юскейсов, которые даже противоречат друг другу, но зато сразу понятно апи. соответственно при tdd это бы разнеслось по десятку методов. а так смотрю в него как туду для апи.
 
Вынос мозга...

Скачал, поставил mongoDB

Хахаха прикол)

Короче если подключить php_mongo

Создать просто файл class Mongo(){} попросить нетбинс сгенерить тест)

получим вот это)
http://pastebin.com/ruBak5RS

Так всегда бывает?
 
Короче в конце концов первые шаги TDD продумывается тестируемый класс, его свойства и методы.
Методы продумываются с точки зрения входящие переменные, возвращаемое значение.
На основе этого строиться каркас класса и создается тест? Правильно все понял?
Не неправильно:
1.Добавление теста
2.Запуск всех тестов: убедиться, что новые тесты не проходят
3.Написать код
4.Запуск всех тестов: убедиться, что все тесты проходят
5.Рефакторинг
6.Повторить цикл

То есть каркас класса не строиться, только в голове. Получается не удобно, так как в нетбинсе есть возможность создавать тесты по ассертам у функций... соответственно для TDD там нет инструмента) то есть создавать класс по тестам)

Так, но если делать вот так, то создавай простой
PHP:
public function testSetDb() {
        $this->object->setDb();
    }

Тесты вообще никакие не запускаются, просто вываливается ошибка php как быть в таком случае? Тест должен не проходить, а он просто не может даже выполниться из-за ошибки... Как быть моки? Или екзепшены? Или че как?)



P.s. почистите тему плиз.
 
craz
собственно это нефишка нетбинса, это скелетон http://www.phpunit.de/manual/current/en/skeleton-generator.html если в phpstrom добавить в настройки путь к скелетону, то появится нужный пункт с меню.
советую начать с настройки окружения для тестов, я обычно подключаю автолод https://github.com/AmdY/SimplePhpFramework/tree/master/test
Соответственно не забудь ide указать путь к phpunit.xml
 
Ура разобрался, всем спасибо. Можно закрывать тему
 
Вставлю свои кять попеек.
Есть книга по TDD, ссылка, где все прекрасно описано, как и когда тестировать (примеры на Java и Python, но в PHP есть такой же PHPUnit).
Лично мое мнение Unit тестирование подходит для тестирования классов, методов, условий и циклов.
Для взаимодействия объектов, модулей и т.п. применяется функциональное тестирование, которое также можно осуществить с помощью PHPUnit, но удобнее было бы это делать с помощью технологии BDD (тестирование поведения), где пишешь обычными предложениями (можно даже на русском языке) фичи, а потом реализуешь эти фичи через класс. Подробнее смотрите на Behat, cucumber (он не только для ruby).

Сам я только учусь практики TDD и BDD.

Попробем разобраться с вашим примером.

Вам необходимо реализовать метод isFileCss($file).
По TDD пишем тест до реализации этого метода.
public function testIsFIleCss()
{
$file = "style.css";
$this->assetTrue(isFileCss($file));
}
Основной принцип TDD - красный - зеленый - рефакторинг.
Красный - при запуске теста (у нас нет еще кода, к-рый тестируем), видим красную полоску.
Пишем быстро простую реализацию этого метода, например так:
function isFileClass($file)
{
return true;
}
Запускаем тест - видим зеленую полоску - успех!

Делаем рефакторинг:
function isFileCss($file)
{
$fileinfo = pathinfo($file);

return $fileinfo['extension'] === 'css';
}
Запускаем тест - зеленая полоска, ура!
И так далее.
Может конечно, мой пример и не идеален, но, надеюсь, суть вы поняли :)
Успехов вам в начинании.
 
  • Like
Реакции: craz
Нельзя сразу писать положительные тесты, иначе получим 100% покрытие зелёными тестами, но кучу фейлов в реальном проекте, особенно при регрессиях.
PHP:
public function testIsFIleCss()
{
    $file = "style.js";
    $this->assetFalse(isFileCss($file));
    $file = "style.css";
    $this->assetTrue(isFileCss($file));
}
 
У меня подошел следующий цикл попыток разобраться с TDD))

Концептуальный вопрос, если мы в классе открываем ftp(функция далее ф.), берем файл(ф.), закрываем фтп(ф.) - нету же никакого смысла тестировать эти функции,
а) они простые,
б) они по идеи должны создавать исключения
в) тестировать их на возникновение исключение тоже тупо?

Но если в этом классе мы хотим производить еще и некие манипуляции с этим файлом то там уже будет больше кода, и вот его уже есть смысл тестировать?
 
craz
смысл TDD, а именно unit-testing не в тестировании того что уже есть, а в написании нового кода(!) через тестирование(!).
 
Ragazzo
Да, но это не значит, что нельзя перейти на TDD методом покрытия существующего кода тестами.
Новый код - да, конечно.
 
fixxxer
не, ну я так и перешел :D но потом забил нах на покрытие уже существующего кода всего, ибо сразу чувствуется где код писался через TDD и где нет. и иногда приходилось "изголяться" с моками и прочим, на уже написанном коде.
 
craz
смысл TDD, а именно unit-testing не в тестировании того что уже есть, а в написании нового кода(!) через тестирование(!).
а я про че?
Я сначала начал писать тест на открытие фтп... Ну так то да я ламо в этом, ничего путного то я не написал, но думаю ладно щас посмотрим сколько сам функция по всем правилам будет занимать.

Получилось чето типа

PHP:
function setConnection(){
        if ( !($this->_connection = ftp_connect($this->getServerAddress())) ){            
            throw new \Exception("Dont create connection",1);
        }
        return $this;
    }

Ну и что тут тестировать то??? Я реально не понимаю(
 
не придирайся) щас уберу.. Я просто перетасовывал методы..(причем все для того, чтобы понять, что можно было бы в таком классе потестировать) В один момент это была другая функция) и называлась даже по другому...
 
а я про че?
Я сначала начал писать тест на открытие фтп... Ну так то да я ламо в этом, ничего путного то я не написал, но думаю ладно щас посмотрим сколько сам функция по всем правилам будет занимать.

Получилось чето типа

PHP:
function setConnection(){
        if ( !($this->_connection = ftp_connect($this->getServerAddress())) ){            
            throw new \Exception("Dont create connection",1);
        }
        return $this;
    }

1)
Это не setConnection. setConnection было бы так
PHP:
function setConnection($connection) {
    $this->connection = $connection;
}

Это connect().

2)
То, что написано, сразу делает код нетестируемым. Надо иметь возможность скормить соединение снаружи:

PHP:
protected function getConnection() {
    if (null === $this->connection) {
        $this->connect();
    }
    return $this->connection;
}

protected function connect() {
     $this->connection = ftp_connect($this->address);
}

public function setConnection($resource) {
      $this->connection = $resource;
}

3)
Если это не класс FtpClient, а что-то выше уровнем, то надо ввести class FtpClient, работающий с ресурсом, а в остальных местах работать с instanceof FtpClient.
 
  • Like
Реакции: craz
PHP:
<?php


namespace Craz\Ftp;

class FtpWorker {

    protected $_connection;
    protected $_serverAddress;

    function __construct($serverAddress) {
        $this->_serverAddress = $serverAddress;
        $this->connect($serverAddress)->ftpLogin("app", "app");
    }

    function getServerAddress() {
        return $this->_serverAddress;
    }

    function ftpLogin($username, $password) {
        if (!ftp_login($this->_connection, $username, $password)) {
            throw new \Exception("FTP credentials are incorrect", 3);
        }
    }

    function connect() {
        if (!($this->_connection = ftp_connect($this->getServerAddress()))) {
            throw new \Exception("Connection has not been established", 1);
        }
        return $this;
    }

    function getConnection() {
        if (null === $this->_connection) {
            $this->connect();
        }        
        return $this->_connection;
    }

   //интересная функция она вообще в реале как может пригодиться не додумаюсь...
    function setConnection($resource) {
        $this->_connection = $resource;
    }

    function __destruct() {
        if ($this->_connection) {
            ftp_close($this->_connection);
        } else {
            throw new \Exception("Connection has not been established. Delete something.", 2);
        }
    }

}
На что в таком классе надо было сначала написать тест?
 
А зачем нужен такой класс? Предполагается, что снаружи будет FtpWorker->getConnection и работа ftp-функциями? Нафиг не нужен такой класс =)

Банальный враппер тестировать смысла особо нет. Все равно не протестируешь. А вот когда здесь будут функции put(), get(), list() и подобные - то вот там, где ты его будешь использовать, сделаешь мок а этот воркер.
 
  • Like
Реакции: WMix
Сверху