Sergey
как тестировать конструирование объекта в phpunit? я правильно понимаю что если ты хочешь это потестить тебе уже не получится юзать setUp?
Sergey
или setUp не будет ничего полезного делать?
Sergey
в смысле тестить конструирование?
Sergey
что это за тест такой?
Sergey
что мол если ты передал в конструктор херню, то должен выкинуть исключение
Sergey
в phpspec я могу написать что-то типа
Sergey
ок, щас
Sergey
$this->beConstructedWith($foo, $bar); $this->shouldThrow()->duringInstantiation();
Sergey
хотя ладно кейс с setUp будет таким же и в спеке
Sergey
там просто это называется let
Sergey
public function testShitstorm() { $this->expectException(\InvalidArgumentException::class); new \Calculator('omfg'); }
Sergey
или же
Sergey
/** * @expectedException \InvalidArgumentException */ public function testShitstorm() { new \Calculator('omfg'); }
Sergey
https://inviqa.com/blog/my-top-ten-favourite-phpspec-limitations
Sergey
You can't have code coverage серьезно?
Sergey
I can't use a data provider
Sergey
:O
Sergey
из коробки - не сможешь, но можно поставить экстеншен
Sergey
дата провайдеров тоже нет
Sergey
I can't mock abstract methods - а интерфейсы можешь?
Sergey
НО
Sergey
вопервых возможно что-то такое сейчас должно появиться в новых релизах ну и опять же есть экстеншены
Sergey
а несколько интерфейсов одновременно?)
Sergey
а несколько интерфейсов одновременно?)
а тебе надо несколько интерфейсов одновременно?)
Sergey
да, были такие кейсы
Sergey
на одной зависимости
Sergey
да, были такие кейсы
а ты считаешь что это нормально?)
Sergey
а почему нет?)
Sergey
ну как тебе сказать... как минимум звучит странно
Sergey
быть может это должен быть не 2 интерфейса а один?
Sergey
может ты не так разделил интерфейсы?
Sergey
может твой класс делает что-то слишком много?
Sergey
не, именно 2 надо было, один как маркер вроде был
Sergey
щас по коду поищу где это было
Sergey
не, именно 2 надо было, один как маркер вроде был
если это два разных объекта (пусть один и тот же просто две зависимости) то норм, но тут тебе phpspec норм
Sergey
иначе что-то не так с сегрегацией интерфейсов
Sergey
а да вот нашел. там коллекция, в нее добавляются элементы интерфейса Filter, но у некоторых элементов может быть еще интерфейс StatefulFilter и вот надо было проверить метод который делает getStatefulFilters
Sergey
да
Sergey
ну... чувствуешь запашек легкий?
Sergey
та не, норм
Sergey
ну это не вонь, это так... как если ты открываешь холодильник и тебе не комфортно
Sergey
ок, твой вариант)
Sergey
я ж задачу не знаю)
Sergey
чем отличается поведение StetefulFilter от Filter и что ты делаешь внутри коллекции?
Sergey
class Filters { /** * @var FilterInterface[] */ private $filters = []; /** * @return FilterInterface[] */ public function getFilters() { return $this->filters; } /** * @param FilterInterface $filter */ public function addFilter(FilterInterface $filter) { $this->filters[get_class($filter)] = $filter; } /** * @param string[] $names * @return FilterInterface[] */ public function getFiltersExcept(...$names) { $filters = $this->filters; foreach ($names as $name) { if (!isset($filters[$name])) { continue; } unset($filters[$name]); } return $filters; } /** * @param $name * @return FilterInterface */ public function getFilter($name) { return $this->filters[$name]; } /** * @return StatefulFilterInterface[] */ public function getStatefulFilters() { $filters = []; foreach ($this->filters as $key => $filter) { if ($filter instanceof StatefulFilterInterface) { $filters[$key] = $filter; } } return $filters; } }
Sergey
вообще можно было сделать расширение интерфейса, но это слишком просто
Sergey
getStatefulFilters
Sergey
только там вижу inscenceof
Sergey
и не понимаю зачем этот метод
Sergey
ну вот надо)
Sergey
ну вот запах
Sergey
короч... пишка ограничений спека в том что отговорки в духе "ну вот надо" там не сработают. Ты тупо не сможешь это протестить и тебе придется подумать получше
Sergey
а поскольку мы со спеком должны работать в контексте tdd
Sergey
то проблемы быстрее находятся
Sergey
вот где он юзается public function createSearchRequest($searchParams) { $searchRequest = new SearchRequest(); $searchRequest->setSearchParams($searchParams); foreach ($this->filtersProvider->getStatefulFilters() as $filter) { $searchRequest->addFilterContext(get_class($filter), $filter->createContext($searchRequest)); } return $searchRequest; }
Sergey
так почему бы тебе для stateful фильтров не завести тупо отдельную коллекцию?
Sergey
зачем?)
Sergey
избавился бы от ифов
Sergey
ну это ж разные интерфейсы
Sergey
и разные штуки
Sergey
если бы у тебя были дженерики
Sergey
то тебе нужно было бы что-то в духе
Sergey
Filters<Filter|StatefulFilter>
Sergey
не. просто StatefulFilter не может сам существовать
Sergey
только как маркер для Filter
Sergey
поэтому List<Filter>
Sergey
...хз стремная хрень
Sergey
короч я хз... сча попробую переписать свои тест кейсы под phpunit и посмотреть насколько тошнотворно
Sergey
если это стремная хрень, зачем ее добавляют в core lib котлина?
Sergey
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-is-instance.html
Sergey
filters.filterIsInstance<StatefulFilter>() вот так бы этот метод выглядел
Sergey
нуууу... хз)
Sergey
компромисы?)
Sergey
😃 да нет, у меня подобные кейсы есть еще в других местах
Sergey
когда есть пачка провайдеров, но все умеют разное. мне нужно выбрать по маркеру их
Sergey
точнее там не маркеры, а полноценные интерфейсы
guga
Про котлин был кстати годный доклад, о том, что любой язык — сполшные компромисы, ну и примеры компромисов, которые они приняли.