«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
Аноним 2017/11/15 14:16:11  №1092373 1
Кто практикует автотесты, вы когда пишете тест для файловой системы (типа некий файл содержит корректные данные), используете библиотеки типа vfsStream или тупо создаете файлы в setUp и удаляете в tearDown?

Я попробовал этот vfsStream, но не смог корректно научить его дублировать реальные пути (т.е. __DIR__). то есть, в кофиге у меня указан параметр rootDir, который типа __DIR__ . '/..' и получается удобно, т.к. везде корректные пути относительно этого пааметра, который лежит в файле конфига. Но проблема в том, что по-модному не потестировать такую конструкцию с моком файловой системы.
Ответы: >>1092613 >>1094219
Аноним 2017/11/15 14:38:16  №1092388 2
ОП, почему ты помогаешь в рамках чанов, а не идешь создавать собственный ресурс-чатик или в телегу?
Ты задумывался о созданий какого нибудь бэкап-сайтика с IRC?
Ответы: >>1092613 >>1094218
Аноним 2017/11/15 19:16:05  №1092503 3
В каких ситуациях нужны отражения? В мануале про них прочел, понял, что они делают и и как работают, но пока плохо понимаю, зачем они могут понадобиться.
Ответы: >>1092507 >>1092613
Аноним 2017/11/15 22:53:13  №1092613 4
>>1092373
По хорошему нужно использовать готовую абстракцию Flysystem: https://flysystem.thephpleague.com/

Это абстракция позволит в тестах подменить хранилище на in-memory: https://flysystem.thephpleague.com/adapter/memory/

То есть в сервис, который работает с ФС передаёшь Filesystem:

class FileUploader
{
public function __construct(Filesystem $filesystem)
{
$this->filesystem = $filesystem;
}

public function upload(File $file)
{
...
}
}

А в тестах можно так:
$filesystem = new Filesystem(new MemoryAdapter());
$fileUploader = new FileUploader($filesystem);
$fileUploader->upload($file);
$this->assertTrue($fileUploader->has($file->getPath));

По твоей ситуации с vfsStream не очень понял тебя, но учти, что если класс тяжело или неудобно тестировать, то это сигнал о том, что код может быть нужно отрефакторить. Этим и хороши юнит-тесты, так как появляется хоть какая-то объективная метрика хорошего кода. Покажи лучше свой пример.

>>1092388
Я не ОП, сайт архивач-для-php-тредов пилится усилиями обитателей треда. Очень тормозил процесс тот факт, что в старых тредах криво сохранённый HTML. Как до конца поправим и задеплоим - напишем об этом тут.

>>1092503
Рефлексией в повседневных задачах пользоваться не нужно, но нужно понимать как работают библиотеки, которые её используют. На рефлексии например работают DI контейнеры с auto-wiring: http://php-di.org/doc/autowiring.html (думаю ты хорошо разберёшься с рефлексией если напишешь свой DI контейнер с автовайрингом - примитивная реализация вряд ли будет больше ~200 строк).
Ответы: >>1092677 >>1094218
Аноним 2017/11/16 00:33:57  №1092677 5
>>1092613
ну по сути vfsStream - это такой же аналог Flysystem. хотя про последнюю не знал, спасибо.

код у меня образно говоря такой:
class Settings
{
const LIB_ROOT = __DIR__ . '/..';
private $cookiePath = LIB_ROOT . '/../var/cookie.txt'; // это библиотека-клиент
public function getCookiePath // это используем везде в библиотеке
public function setCookiePath($path)
{
$this->cookiePath = self::LIB_ROOT . $path;
}

class Auth
{
// тут всякая логика
}

class AuthTest
{
protected function setUp()
{
$this->settings = new Settings();
$this->settings->setCookiePath('/var/test_cookie.txt');
}

и далее создаем этот файл и тестируем его

моя задача - определять путь к куки как постоянный, т.е. чтобы мы могли определить его в любом месте проекта и он был одинаковым независимо от расположения файла, где мы его определили, в иерархии папок. Но возникла проблема - не протестировать с использованием того же vfsstream. видимо надо рефакторить, но я не понимаю как. может, кто-то подскажет?
Ответы: >>1094217 >>1094309
Аноним 2017/11/16 01:03:23  №1092684 6
Анончики, не смейтесь надо мной, я очень далек от кодинга и тут решил почитать составленный вводный курс для чайников. Там мне попалась задачка, цитирую: "Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?"

Далее, я решил посчитать, к какому году жизни у него накопится этот миллион. Вышел такой вот код (простите, я поспешил и не стал расписывать значения переменных, но тут должно быть все предельно ясно) :

<?php

for ($x = 10000; $x == 1000000; $x = $x+($x*10/100)) {


for ($y = 16; $x == 1000000; $y ++) {

echo "В $y будет $x на счете \n";
}
}


?>

А дальше ничего не происходит. Вы, наверное, улыбаетесь, читая этот пост, мол, такую простоту не может решить, но я нахожусь в тупике, программа выполнена успешно, пишется, но ничего не происходит. Никакого подсчета и вывода сообщений. В чем заключается моя ошибка? Заранее благодарю. Писал и запускал это на айдеоне.

Аноним 2017/11/19 09:27:47  №1094217 7
>>1092684

Формулу увеличения суммы лучше вынести из заголовка цикла в тело на отдельную строчку. А то код труднее читать и труднее найти проблему.

Почему у тебя 2 вложенных цикла? Ты можешь описать словами, какие команды должен выполнять PHP?

Я твой код вижу так:

1) присвоить $x значение 10000
2) проверить: если $x больше миллиона, перейти к шагу 10
3) присвоить $y знаечние 16
4) проверить: если $x больше миллиона, перейти к шагу 10
5) написать: "В $y будет $x на счете \n"
6) увеличить $y на 1 ($y++)
7) перейти к шагу 4
8) увеличить $x на 10%
9) перейти к шагу 2
10) конец программы

Попробуй выполнить этот алгоритм "вручную", выполняя роль PHP. Если ты все сделаешь правильно, то ты увидишь, почему эта программа будет выполняться бесконечно ("зациклится").

>>1092677

Я обычно не заморачиваюсь и в тесте просто создаю временную папку в /tmp, которую потом уничтожаю.

Чтобы использовать абстракции вроде Flysystem, твой код должен принимать снаружи объект Filesystem. Тогда его можно будет подменить в тесте.

> моя задача - определять путь к куки как постоянный, т.е. чтобы мы могли определить его в любом месте проекта и он был одинаковым независимо от расположения файла, где мы его определили, в иерархии папок.

Простой вариант: ведь код должен испоьзовать путь из Settings

Более сложный вариант: код должен принимать объект Filesystem и работать с файлом через него, тогда этот объект можно подменить в тесте. То есть, надо использовать DI. Урок про DI: https://github.com/codedokode/pasta/blob/master/arch/di.md
Ответы: >>1094366
Аноним 2017/11/19 14:58:46  №1094366 8
>>1094217
> Я обычно не заморачиваюсь и в тесте просто создаю временную папку в /tmp, которую потом уничтожаю.
Я тоже смотрю, что даже в серьезных проектах делается зачастую как раз так, но с другой стороны в самом мануале по phpunit указана эта библиотека для работы с файловой системой и такой подход кажется изящным (пока не попытаешься использовать, по крайней мере).

>Более сложный вариант: код должен принимать объект Filesystem и работать с файлом через него, тогда этот объект можно подменить в тесте

Спасибо! Так и поступлю.

> Тут нет ошибки? Локальный путь конкатенируется с путём из виртуальной ФС, так работать не будет.
Ну как бы есть, потому что я как раз и не знал, как связать их между собой.

> И может быть для тестирования аутентификации не нужно сохранять куки на ФС?
Там еще идет тестирование на то, что файл куки создается корректно (есть нужная папка, нужные права и т.д.).

А вот еще вопрос по случаю: ты говоришь, тесты должны быть простыми. И вроде да, ведь юнит-тест тестирует минимально самостоятельную часть кода, метод там или класс. Но есть же некоторые вещи, которые тоже хочется протестировать, но они уже выходят за рамки одного класса. Например, что твой код корректно обрабатывает присланные каким-то сторонним сервером по АПИ данные. Тогда нужно создавать класс-мок и
это уже по идее не юнит-тест. Или что при авторизации корректно создается файл куки. С такими вещами как поступать? Не тестировать их с помощью Phpunit, а, допустим, через codeception?
Ответы: >>1097372
Аноним 2017/11/19 16:37:33  №1094436 9
Только начинаю постигать php, не могу понять, почему не записываются данные из формы в txt файл?
https://pastebin.com/EqAHm1GW
Ответы: >>1097372
Аноним 2017/11/24 21:51:21  №1097372 10
>>1094436

Надо смотреть лог ошибок веб-сервера (если ты используешь mod_php и Апач), он на винде по умолчанию лежит в папке Апача, на линуксе в /var/log. Так гадать смысла нет.

>>1094366

> Но есть же некоторые вещи, которые тоже хочется протестировать, но они уже выходят за рамки одного класса
Для этого и придуманы интеграционные тесты, которые тестируют совокупность нескольких модулей кода. И есть тесты, которые тестируют приложение целиком в сборе. Я не говорил, что они не нужны, хотя есть так называемая "пирамида тестирования": https://martinfowler.com/bliki/TestPyramid.html

> Например, что твой код корректно обрабатывает присланные каким-то сторонним сервером по АПИ данные.
Я не люблю конечно такие тесты, так как АПИ могут меняться, плюс часто они подробно не документированы и об ошибках в коде ты узнаешь только когда он не сможет что-то обработать. Но конечно, сохранить ответ API и проверить, что код его разбирает и не падает, вполне допустимо.

> Тогда нужно создавать класс-мок и это уже по идее не юнит-тест
Я не уверен тут в терминологии, юнит- или не юнит-тест это. Мы же тестируем один класс, а не их совокупность.

> Или что при авторизации корректно создается файл куки.
Мне этот тест не нравится. У твоей программы какая цель? Создавать файлы кук? Или эти файлы как-то используются потом? Если второе, то лучше это и тестировать. А то тест получается, завязан на знание о внутренней логике работы программы. Завтра ты поменяешь имя файла или перенесешь куки в базу и тест сломается.

Вообще, если код в ходе теста должен куда-то обращаться к стороннему серверу, то это тоже плохо, так как ты тестируешь не только свой код, но и код на том сервере, а также его работоспособность и работоспособность каналов связи с ним. Может быть такое, что этот тест часто будет падать. Или ты превысишь какую-нибудь квоту на число запросов. Но такое тоже допустимо в тесте, который тестирует все приложение насквозь.

А также, АПи можно мокать. Есть даже программы, которые по моему могут записывать пары запрос/ответ, а потом ответ воспроизводить.

> Не тестировать их с помощью Phpunit, а, допустим, через codeception?
Ну, это не принципиально. Используй то, что удобнее.
Ответы: >>1097572
Аноним 2017/11/25 14:27:22  №1097572 11
>>1097372
>У твоей программы какая цель? Создавать файлы кук? Или эти файлы как-то используются потом? Если второе, то лучше это и тестировать. А то тест получается, завязан на знание о внутренней логике работы программы.

в принципе, цель данного функционала - всегда быть залогиненным при корректном пароле. и это как бы получается внутренняя логика, да. с другой стороны, это публичная библиотека и хочется на нее повесить плашку "100% code coverage" как у всех :) чтобы я пришел устраиваться на работу и на собеседовании такой эту плашку показал и мне сразу +10к к зп (просто я вижу, что на собеседованиях часто не настолько внимательно разбирают чужой код, как тут, например)

еще вопрос: есть приватный метод, который вызывается в публичном. например, мы делаем несколько запросов по апи (публичный метод addEntity(EntityInterface $entity)) и между ними должны выдерживать паузу в секунду, чтобы нас не забанили (приватный метод waitOneSec()) мы должны его тестировать через публичный, правильно? или вообще не должны?
Ответы: >>1097583 >>1097585 >>1097591
Аноним 2017/11/25 15:15:11  №1097591 12
>>1097572
> повесить плашку "100% code coverage" как у всех :)
У кого "всех"? В реальной жизни никто на эти бесполезные цифры время не тратит, почитай:
- https://medium.com/@nicklee1/why-test-code-coverage-targets-are-a-bad-idea-1b9b8ef711ef
- http://www.databonanza.com/2012/08/the-evils-of-code-coverage-and-other.html
- https://news.ycombinator.com/item?id=14297289

> показал и мне сразу +10к к зп
Глупости. Тесты пишутся для того, чтобы меньше времени тратить на обнаружение и исправление багов, чтобы проще было обновляться (неважно что - фреймворк или версию PHP), чтобы проще можно было рефакторить, так как с тестами ты получаешь волшебную кнопку, которая рапортует тебе о возникших проблемах. И даже при наличии тестов может возникнуть проблема как у этого >>1097568 анона, тогда все твои 100% коту под хвост.
Ответы: >>1098085
Аноним 2017/11/26 14:56:41  №1098085 13
>>1097591

> И даже при наличии тестов может возникнуть проблема как у этого >>1097568 анона, тогда все твои 100% коту под хвост.

При наличии тестов он бы сразу обнаружил проблему (если бы на dev обновил PHP до той же версии и прогнал бы тесты).