Я полностью согласен — RecordStorage нужно покрыть интеграционным тестом, чтобы гарантировать его работу, как ожидается. Просто с тем кодом, где использовался private, вам нужна магия PHP, чтобы добраться до private, нам требуется знание черного ящика, тела функции, знания о её реализации...
Никогда не тестируйте защищённые/приватные методы
Основная причина: они влияют на то, как мы тестируем функции, определяя сигнатуру поведения: при таком-то условии, когда я ввожу А, то ожидаю получить Б. Приватные/защищённые методы не являются частью сигнатур функций.
А с кодом, который без private, мы проверяем результат RecordStorage::load($id) — подсовывая в constructor нужные нам состояния $cache и $storage, проверяем возвращаемый Record — никакой магии и тест будет читаться просто:
Дано RecordStorage и когда $cache и $storage такие-то, тогда RecordStorage::load($id) возвращает такой-то Record.
При private тестируется: будет ли второй раз при запросе к load отрабатывать кэш. А в третий, а в четвёртый — уверены?
Без private тестируется:
будет ли возвращён по id ожидаемый Record, который в cache, если он там имеется
будет ли возвращён по id ожидаемый Record, который в storage если в cache его нет.
Тут дело в том, что классу RecordStorage позволительно очень многое. По сути он создавался как сервис получения данных из хранилища.
В качестве хранилища у вас выступает doLoad() или $this->db->select('...') или т.д., по хорошему этот код должен быть в отдельном классе.
Сейчас за хранилище отвечает Сервис API получения данных из хранилища. Это и есть причина того, что есть потребность тестировать RecordStorage:load(). А если переписать код как указано ниже, то и тестировать нечего.
final class RecordStorage {
/** Cache backend */
private $cache;
/** Cache backend */
private $storage;
public function load($id): Record
{
if ($record = $this->cache->get($id)) { // протестировано отдельным тестом
return $record;
}
$record = $this->storage->dataById($id); // протестировано отдельным тестом
$this->cache->set($id, $record); // протестировано отдельным тестом
return $record;
}
}
Пункт "Никогда не тестируйте защищённые/приватные методы", да и вообще рекомендации из статьи в целом хороши тем, что заставляют думать и писать "чистый код".
$this->cache->get($id) нужно протестировать отдельным тестом.
$this->cache->set($id, $record); тоже нужно протестировать отдельным тестом.
doLoad() должен быть публичным, с вынесением в отдельный класс — тоже должен быть протестирован на граничные случаи.
Тогда RecordStorage:load() тестировать нет необходимости. RecordStorage превратиться сервис, который получает данные от протестированных компонентов и делегирует их в другие протестированные компоненты.
Так что для пункта 5. Никогда не тестируйте защищённые/приватные методы исключений не бывает ;)
var speed = 1000;
var clickEvent = new MouseEvent("click");
var elements = [].slice.call(document.getElementsByClassName("cell"));
elements.sort(function(a, b){return a.textContent - b.textContent;});
for(var i = 0; i < elements.length; i++) {
setTimeout(function(element){element.dispatchEvent(clickEvent);}, i*speed, elements[i]);
}
php yii migrate/create create_user --fields="username:string(255):notNull(),email:string():notNull()"
// проверяем, поправляем код миграции в файле
php yii migrate
php yii gii/model --modelClass="User" --tableName="user" --ns="backend\models"
// поправляем, проверяем код модели в файле
php yii gii/crud --controllerClass="backend\controllers\UserController" --modelClass="backend\models\User"
// Теперь осталось код чуточку подправить и показать PM ;)
Скелет CRUD приложения для вашей модельки готов, который вполне работает. При этом не надо было запускать браузер и "программировать мышкой".
Вы на 100% правы.
Шах и мат :)
Юрист, преподаватель, который разобрался в PHP, React, Docker, GitHub, OSM, нейронках, парсингах ... Да Вы молодец!
Проблема: производительность - рендер Page и всех его дочерних компонентов каждый раз при вводе в input.
Причина: вызывается setState в handleChange при onChange input элемента
Решение: убираем состояние useState() для name;
без всяких useCallback
Пример в статье подобран неудачно ...
Агенты же тоже могут себе увеличить силу…
Чтобы уверенно разойтись по домам с шампанским надо как-то так:
у машин нет шансов против Нео.
условие всегда
false
как бы агент не рыпался ;)Я полностью согласен — RecordStorage нужно покрыть интеграционным тестом, чтобы гарантировать его работу, как ожидается. Просто с тем кодом, где использовался private, вам нужна магия PHP, чтобы добраться до private, нам требуется знание черного ящика, тела функции, знания о её реализации...
А с кодом, который без private, мы проверяем результат
RecordStorage::load($id)
— подсовывая в constructor нужные нам состояния$cache
и$storage
, проверяем возвращаемый Record — никакой магии и тест будет читаться просто:Дано RecordStorage и когда
$cache
и$storage
такие-то, тогда RecordStorage::load($id) возвращает такой-то Record.При private тестируется: будет ли второй раз при запросе к load отрабатывать кэш. А в третий, а в четвёртый — уверены?
Без private тестируется:
Тут дело в том, что классу
RecordStorage
позволительно очень многое. По сути он создавался как сервис получения данных из хранилища.В качестве хранилища у вас выступает
doLoad()
или$this->db->select('...')
или т.д., по хорошему этот код должен быть в отдельном классе.Сейчас за хранилище отвечает Сервис API получения данных из хранилища. Это и есть причина того, что есть потребность тестировать
RecordStorage:load()
. А если переписать код как указано ниже, то и тестировать нечего.Пункт "Никогда не тестируйте защищённые/приватные методы", да и вообще рекомендации из статьи в целом хороши тем, что заставляют думать и писать "чистый код".
[удалено] не туда..
По хорошему:
$this->cache->get($id)
нужно протестировать отдельным тестом.$this->cache->set($id, $record);
тоже нужно протестировать отдельным тестом.doLoad()
должен быть публичным, с вынесением в отдельный класс — тоже должен быть протестирован на граничные случаи.Тогда RecordStorage:load() тестировать нет необходимости. RecordStorage превратиться сервис, который получает данные от протестированных компонентов и делегирует их в другие протестированные компоненты.
Так что для пункта 5. Никогда не тестируйте защищённые/приватные методы исключений не бывает ;)
Предполагаю, что одна из причин, по которой он в топе — это отправка этого заголовка по умолчанию в PHP при старте сессии (Pragma: no-cache).
http://php.net/manual/ru/function.session-cache-limiter.php
Там рождается ещё один слоник.
Когда лень :/
Первый вариант кстати тоже, он заменяется на:
Ну и демо данные набросать ещё можно, по аналогии с этим PR:
Мне вот очень зашло:
Скелет CRUD приложения для вашей модельки готов, который вполне работает. При этом не надо было запускать браузер и "программировать мышкой".