Как стать автором
Обновить
4
0

Пользователь

Отправить сообщение
Строго говоря, алиасы для команд это вся суть Makefile. Даже если учитывать команды для компиляции и сборки бинарников, в типичном Makefile почти всегда алиасы общего назначения (PHONY).
make install классический пример.
Просто с тем кодом, где использовался private, вам нужна магия PHP, чтобы добраться до private, нам требуется знание черного ящика, тела функции, знания о её реализации...
В данном конкретном случае магии не требуется. Можно мокая, кеш и задать что то вроде $cache->expects($this->never()). По поводу знания реализации. Конечно для тестирования реализации нужно знать реализацию. Тут возникает интересный вопрос. Должна ли инкапсуляция распостранятся на тесты? Я думаю для этого нет причин.

А с кодом, который без private, мы проверяем результат RecordStorage::load($id) — подсовывая в constructor нужные нам состояния $cache и $storage, проверяем возвращаемый Record — никакой магии и тест будет читаться просто
private это просто способ организовать внутреннее устройство класса. Оно может быть любым, как вам захочется. Отказываться от private методов только из-за того чтобы упростить тестирование, как то не правильно, имхо.

Это всё были детали конкретного сильно упрощённого примера. Что если внешних зависимостей вообще нет? Что если класс сам прозводит данные, например вычисляет какой нибудь сложный хеш для переданной строки и кеширует это в приватной переменной?
Главная фича Make, отслеживание изменённий в зависимостях здесь не используется. Всё тоже самое можно сделать с помощью обычного Баш скрипта со свитчем команд. Было бы даже по красивее. Синтаксис Make файлов мягко говоря не инуитивный.
// протестировано отдельным тестом
Тестирования зависимостей по отдельности, ничего не гарантирует. В данном случае нужен интеграционный тест, чтобы убедится что RecordStorage умеет корректно с этими зависимостями.

В качестве хранилища у вас выступает doLoad() или $this->db->select('...') или т.д., по хорошему этот код должен быть в отдельном классе.
doLoad() это просто внутренняя обёртка над хранилищем. То что вы убрали, её никак не поможет проверить в тесте, то что данные при повторном запросе берутся из кеша, а не из БД.

Пункт «Никогда не тестируйте защищённые/приватные методы», да и вообще рекомендации из статьи в целом хороши тем, что заставляют думать и писать «чистый код».
Удаление приватных методов, не сделает автоматически код «чистым».

Тема тестирования приватных методов это частный случай более широкой темы тестирования деталей реализации. В общем случае реализация может находится и в публичном методе (как в вашем примере). Нужно ли её тестировать? Зависит от цели тестрования. Если ваша цель просто убедиться в том, что все публичные интерфейсы работают как надо, то тестировать детали реализации нет смысла. Но большое заблуждение при этом думать, то что корректность работы публичного интерфейса сервиса гарантирует отсутствие багов в нём. Сервис может отдавать корректные результаты внешним потребителям, но при этом делать не нужные запросы к внешним API, создавать/удалять сущности в базе, засорять системный лог и много других не запланированных вещей, которые тест публичного интерфейса не обнаружит.
$this->cache->get($id) нужно протестировать отдельным тестом.
$this->cache->set($id, $record); тоже нужно протестировать отдельным тестом.
$cache это зависимость, которая само собой должна иметь свой отдельный тест. В данном случае задача состоит только в том, чтобы протестировать логику кеширования в RecordStorage и интеграцию с cache сервисом.

doLoad() должен быть публичным, с вынесением в отдельный класс
Зачем? doLoad используется только внутри этого класса. Внешним потребителям не нужно знать про него. В общем случае его может вообще не быть.
public function load($id): Record
{
    if ($record = $this->cache->get($id)) {
        return $record;
    }
    $record = $this->db->select('...') ; // Some slow SQL query to the database.
    $this->cache->set($id, $record);
    return $record;
}
Рефакторишь класс, обновляешь соответствующий юнит тест. Вроде всё работает, тесты зеленые, а потом выясняется что это класс используется как зависимость в другом классе. Так как в юнит тестах, обычно вместо реальных зависимостей используют test-doubles, то изменения в работе зависимостей могут остаться не замеченными.
Имхо, обычные каптчи с картинками без дублирующей аудио каптчи уже потеряли актуальность из-за проблем с доступностью.
Ок, а если метод используется в 5 публичных функциях, на основе какой мне тестировать?
Как раз приватный метод тестировать обычно не нужно совсем, потому что он относится к деталям реализации. Если все public/protected методы покрыты тестами, то можно быть уверенным, что этот класс (юнит) работает в соответстветствии со спецификацией/контрактом.
Хотя бывают исключения. Иногда надо убедиться, что класс делал или не делал вызовы к внешним API, например через системые вызовы. Если это трудно замокать, то придётся тестировать именно реализацию.
Пример.
final class RecordStorage {

    /** Cache backend */
    private $cache;

    public function load($id): Record
    {
        if ($record = $this->cache->get($id)) {
            return $record;
        }
        $record = $this->doLoad($id);
        $this->cache->set($id, $record);
        return $record;
    }

    private function doLoad(): Record
    {
        // Call some external API.
        $record = ...;
        return $record;
    }

}
Тут помимо тестирования RecordStorage:load() желательно ещё проверить что данные корректно кешируются, а для этого в тесте надо убедится, что RecordStorage:doLoadData() не вызывался при повторном запросе.
этот язык — не самый дружелюбный в плане работы с IPv6
А какие языки являются дружелюбными в этом плане?
Никогда не тестируйте защищённые/приватные методы
Есть приложения в которых наследование является точкой расширения. Поэтому protected методы являются частью публичного API, который само собой нужно тестировать.
Но когда мы говорим о реальном коде, например реального сайта, то практически 90% функций имеют зависимость на что-то. И потому 90% юнит-тестов превращаются в интеграционные тесты.
Обычно эти зависимости заменяются на test-doubles.
Справедливости ради, у автора поста итоговая картинка красивее, чем cmatrix.
Наверное, из-за отсутствия поддержки полупрозрачных шрифтов в стандартных терминалах.
А так как все зависимости тоже покрыты тестами — то их правильная работа тоже гарантируется.
Unit test 2, Integration test: 0

Go стал стандартом де-факто в области создания инструментов командной строки.
Можете обосновать это?
По вашей логике допуск баластного резистора в цепи питания светодиода должен таким же как у резистора в колебательном контуре генератора если они используются в одном устройстве.
Я думаю точность резистора определяется не устройством в котором он используется, а требованиям конкретной электрической схемы.
PHP
The target label must be within the same file and context, meaning that you cannot jump out of a function or method, nor can you jump into one.
языки где был тот самый страшной goto пропали ещё в конце 80
PHP, С, C++, C# вроде никуда не пропали.
Какая разница какие там еще есть методы в этом классе? Эти константы публичные и не требуют создания объекта. Если у вас в проекте не используется symfony/http-foundation, можно взять к примеру yiisoft/http, там нет ничего лишнего. Есть куча других похожих проектов, для разных ЯП. Константы в классах удобны тем что не засоряют глобальный неймспейс и загружаются автоматически. Т.е. не нужно инкудить файл самостоятельно.

Информация

В рейтинге
Не участвует
Откуда
Россия
Дата рождения
Зарегистрирован
Активность