Cypress tests organizing (or any e2e/ui tests)

Nowadays cypress is quite a hype technology (I am saying this in Fall 2020, everyone knows how rapidly js world can change ;))

"Cypress is a next generation front end testing tool built for the modern web."

https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshel

I had some experience with Behat and other types of tests like unit/integarational, but today I will tell you about e2e.

When I wrote Behat tests I didn't think a lot about how to structure my test cases in a maintainable way. This led me to the antipattern called "Single-Layer Architecture"[1].

Extending such tests quickly becomes a mess and tends to become an ineffective work:

  1. You can't focus on business logic, you always need to remember low-level details to introduce a new step definition
  2. Your low-level solutions are often duplicated, and you even don't notice that
  3. Changing testing framework means rewriting or updating all step definitions!

Fortunately there is an approach which is very easy to follow and which mitigates mentioned issues.

en uk

How games (or any pet projects) should never be developed

This story is about wasting time and life. It is about Attraction Wars.

Attraction Wars is an online browser game I developed in my free from job time.

I am surrounded with "success stories". But very few new projects (or startups if you want) succeed. According to the different sources, it is less than 10%, I more believe sources which say that it is even less than 1%.

Of course, it dramatically depends on which stage startup was accounted for this statistics... But this story is not about it. I just feel that I should write "story of NOT success", just to dilute all that success stories with other fairy tale.

Honestly I think that history of Attraction Wars development is an example of how games (or any pet projects) should never be developed.

However it teached me a lot, including technologies and outlook, so I hope this experience will be useful for someone. Or only for me as reminder.

But if you are interested of this deep dive to cave, then please go ahead.

Непрерывная интеграция с использованием Travis CI и Behat

Эта заметка начинает цикл заметок о процессах разработки и деплоя приложений. Для начала покажу, как с помощью сервиса Travis CI можно относительно легко реализовать процесс проверки качества и работоспособности кода.

Практику постоянной проверки сборки на наличие дефектов называют Непрерывная интеграция (Continuous Integration).

Вопрос написания тестов в этой статье не будет рассмотрен - это тема другой статьи. Сделано предположение, что у вас уже настроен Behat, и тесты уже могут быть локально запущены с использованием Selenium.

Для начала, проверим, нет ли в коде нарушений установленного код стайла. Это позволит ознакомиться и начать использовать Travis CI. Если у вас нету тестов - настоятельно рекомендую использовать как минимум проверку стиля кода.
Обоснование важности консистентности кода и и его стиля можно найти во множестве мест, например, Стив Макконнелл “Совершенный код” часть 7 раздел 31.

Как в PHP узнать строку, на которой прервалось исполнение

При работе со старым кодом иногда очень сложно найти место, на котором прервалось исполнение. Конструкции типу die, exit и т.д. - очень плохая практика, но много легаси кода (и не только - я ничего плохого не говорю о Wordpress, так что молчу) ими злоупотребляют. Одна из самых больших проблем подобных конструкций - то, что их сложно найти и отладить. (Используйте exception!)

Но когда все же стоит задача найти место, где прерывается исполнение кода, можно воспользоваться следующим сниппетом:

ru en

Refreshing Nested Set Tree Indexes in Symfony

Tree

Once I used Nestedset behavior for Doctrine, Symfony in a project, and faced issue with broken indexes. (You can read how Nested Set works here). This happened because low-level MySQL query executed during migration, and because of this Doctrine events responsible for refreshing indexes was not executed. To fix that a Symfony Command was written, which refreshes indexes. This is just example. Better way is to move this code to the service and add one more migration which will refresh indexes. Here is just simple example how this issue can be solved.

Argument of the command is an entity to refresh.

Загрузка файлов в Symfony

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

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

В этой заметке попытаемся показать возможные пути решения поставленной задачи, как с помощью готовых решений (VichUploaderBundle, IphpFileStoreBundle), так и с помощью собственной реализации (в контроллерах Symfony и админ классах SonataAdminBundle).

Добавление комментариев на сайт

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

В этой заметке вы узнаете один из самый простых (но, субъективно, один из наиболее предпочтительных) способов добавить комментарии на сайт - простой пример для новичков + варианты для более продвинутых веб-мастеров.

Действительно, для чего изобретать велосипед и писать кучу кода, который в будущем еще придется поддерживать, фиксить и т.д., если есть куча готовых решений от сторонних сервисов (речь идет о социальных сетях + disqus)?

Value Object'ы у Symfony формах

DecompositionSymfony разработчики часто задаются вопросом, как заставить Symfony формы работать с value-object'ами. Давайте, для примера, представим тип Money как объект с двумя полями $amount и $currency:

class Money
{
    private $amount;
    private $currency;

    public function __construct($amount, $currency)
    {
        $this->amount = $amount;
        $this->currency = $currency;
    }

    public function getAmount() // ...
    public function getCurrency() // ...
}

Можете ли вы создать form type для этого класса без методов setAmount() и setCurrency()? В этой заметке вы научитесь этому.

Версионность ассетов при использовании gulp

assetsПри изменении клиентского кода нужно как-то заставить браузер клиента перезагрузить измененные файлы. Эта проблема достаточно распространенная. Скорее всего, вы столкнетесь с ней вне зависимости от того, какими технологиями пользуетесь при веб-разработке. Этот пример о решении проблемы при создании фронтенд проекта с использованием javascript и gulp.

Решить можно несколькими способами.

Пусть, например, 7e50961489 - это новая версия ассетов. На самом деле, она может быть любой, главное, чтобы отличалась от тех, что были раньше. Можно просто нумеровать - 1, 2, 3 и т.д. Но так не слишком удобно. Дальше станет понятно, почему.

Sequence Master Game

Sequence Master Game - игра для проверки скорости реакции. Кликайте по наибольшем среди доступных чисел (можно выбирать несколько чисел на каждом шаге) и делитесь рекордом с друзьями.

Ключевые особенности/геймплей:

1) Доступно 7 уровней

2) За отведенное время вы должны успеть прокликать числа от наибольшего до наименьшего.

3) За каждый выбор начисляются очки. Их количество зависит от скорости выбора игрока и величины выбранного числа. В случае ошибки игра не прекращается, но начисляется штраф.

4) Игра прекращается, если не успеть выбрать правильное число за отведенное время. После окончания игры есть возможность расшарить результат.

5) Респонсивность (должно работать на смартфонах), анимация и прочие свистелки =).

Поиграть можно перейдя по ссылке: https://rg.folkprog.net

Gulp-файл для frontend проекта

Решение не претендует на идеальность. Но вполне подойдет для разработки небольшого frontend проекта, написанного с использованием coffeescript и less. Важное замечание: использование бекенда не предусмотрено. Nodejs использован только для билда ассетов (такое решение удобно, к примеру, если вы планируете создать гибридное оффлайн приложение для смартфона).

Ключевые особенности нашего проекта, и, как следствие, gulp-файла:

1)  Поддерживает разные среды (prod, dev, etc)

2) Компиляция и минификация less, CoffeScript файлов, объединение нескольких в один (конкатенация)

3) Поддержка тестов (jasmine)

4) В dev-среде работает watch (динамически перебилдивает ассеты при изменении исходников)

Создание респонсивных таблиц с помощью css

В этой заметке мы рассмотрим, как можно использовать таблицы в респонсивных шаблонах и как мы можем сделать удобным использование таблиц на мобильных устройствах.

При создании респонсивных таблиц вы столкнетесь с множеством проблем:

  • Слишком много колонок
  • Слова вылазят за границы ячеек
  • Ширина колонки становится слишком малой
  • Если у вас много строк, при скроле вы не сможете видеть заголовки колонок

В этой заметке, надеюсь, мы исправим все эти проблемы путем использования респонсивного css-решения.

Junior vs Senior разработчик: в чем, в конце концов, разница между ними?

Junior vs Senior engineerКажется, что есть резкий контраст между этими уровнями. Но на самом деле, какое различие между Junior и Senior разработчиком?

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

Этот вопрос может показаться глупым и очевидным, но какой же ответ на самом деле?

Инкапсуляция с помощью замыканий в JavaScript

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

Если переменная или объект в JavaScript не помещены внутрь какой-либо функции, то они становятся глобальными. Все глобальные элементы в JavaScript являются свойствами глобального объекта. Для браузера это объект window. При этом конструкции for, if и другие не влияют на видимость переменных.

Создание глобальных переменных, как правило, нежелательно, так как оно может привести к трудно обнаружимым ошибкам, и усложняет перенос кода в другие приложения.