Как я проверял игру без браузера
В игре добавилось пять событий: мышь, миска, гроза, тыгыдык и огурец-великан. Проверять каждое руками долго: надо дожить до нужного уровня и дождаться, пока выпадет именно то событие. Поэтому я запустил игру в Node.js, вообще без браузера.
Подмена браузера
Игра обращается к document, canvas, localStorage и AudioContext. Для теста всё это заменено заглушками. Самая удобная — canvas через Proxy: любой метод, о котором я не подумал, просто ничего не делает, а fillText заодно проверяет, что координаты не превратились в NaN:
const ctx = new Proxy({}, { get(t, k) {
if (k === 'measureText') return (s) => ({ width: String(s).length * 10 });
if (k === 'fillText') return (s, x, y) => {
if (!isFinite(x) || !isFinite(y)) throw new Error('NaN coords for ' + s);
};
return () => {};
} });Чтобы добраться до внутренностей игры, тест перед запуском дописывает в код маленький объект с нужными функциями. В сам файл на сайте это не попадает.
Бот вместо игрока
Для каждого события тест включает его принудительно и ведёт котика так, как вёл бы человек: за мышью, к миске, к месту удара молнии, а от великана в другую сторону. После этого проверяет итог: мышь поймана, миска накормила, достижение открылось, великан ударил, если не увернуться.
Что нашлось
Ошибок в коде тест не нашёл, зато нашёл проблему с балансом. Бот поймал мышь девять раз за девять секунд. С мышкой или пальцем человек водит котика почти так же точно, значит, это был бы самый щедрый источник очков в игре.
Теперь мышь после поимки дольше прячется, а после третьей убегает в норку. Достижение «Мышелов» как раз за три мыши, так что оно осталось достижимым.
Ещё одна вещь, о которой пришлось помнить: сервер не примет рекорд, если очков больше, чем можно честно набрать за время партии. Поэтому награды у новых событий скромные, иначе честный хороший результат выглядел бы как читерский.
Цвета всё равно пришлось проверять глазами. Тест ловит ошибки в логике, а различаются ли огурцы и рыба на экране, он не скажет.