Автор оригинала: Kevin Lamping.
В последнее время я прокладывался на Кодирование приложения для рабочего стола Prototype с использованием электрона и Vue Отказ
Это было действительно весело отпустить все эти «лучшие практики» и просто код как можно больше и как можно быстрее.
Одна из этих лучших практик, которые я передал, это тестирование подразделения. Я 100% верю в ценность этого, но только в правильных обстоятельствах.
На этом этапе моего проекта у меня нет определенного спецификации, мои функции приходят и идут, как я чувствую, и код, который я пишу, – это очень процедурный (например, подключать мою базу данных к моим вариантам Vue).
Для меня реальная выгода тестирования подразделений появляется при использовании логических операторов (т. Е. Если это тогда) в вашем коде. У меня сейчас нет много этого.
Но … был один компонент, который требовал немного манипуляций данных. Мне нужно было превратить массив путей файлов в структурированный объект.
Мне нужно повернуть это:
['./test/specs/a.js', './test/specs/b.js', './test/specs/a/a.js']
В чем-то вроде этого:
[{ title: 'test', children: [{ title: 'specs', children: [{ title: 'a.js' }, { title: 'b.js' }, { title: 'a', children: [{ title: 'a.js' }] }] }] }]
В то время я работал над кодом, я знал, что это будет отличный шанс использовать единичные тесты. Я знал, что был мой вклад, и я знал, что я хотел, чтобы мой результат был.
Быстрое примечание: я собрал видео, охватывающую все это на моем канале YouTube
Набор тестов подразделений действительно поможет мне проверить мой код работает, плюс дайте мне четкие цели и немедленная обратная связь, Оба существенных условия попадания в хорошее состояние потока Отказ
Несмотря на это, я не хотел отвлекать себя от записи фактического кода.
У меня еще не написал какие-либо тесты на проект, поэтому у меня не было создана тестовая структура. Они не слишком сложны, чтобы бегать в эти дни, но я действительно не хотел, чтобы охватить кроличье дыру, исследующую лучшие рамки, библиотеку Myce, и т. Д. Использование и как включить все это в электрон/Vue приложение.
Мне очень нужна дешевая, простая альтернатива тестовой структуре, и именно поэтому эта идея тестирования единиц «Ad Hoc» приходит.
Написание очень базовой единицы тестовой структуры
Существует два основных функция, которые необходимо запустить тест на единицу: тестовый бегун и библиотеку утверждения.
Nodejs поставляется с Простая библиотека утверждения в качестве основного модуля. И очень базовый тестовый бегун можно записать примерно в 10 строках кода.
С этим у меня был базовый план на месте, чтобы установить мою код:
- Переместите функцию, которую я хочу проверить в отдельный файл, чтобы облегчить загрузку
- Создайте новый тестовый файл Далее
- В этом файле загрузите библиотеку «Assert» и мой файл функции, напишите некоторые тесты и добавьте мой мини-бегун до конца.
- Запустите мои тесты в командной строке, используя
Узел
овладение
Перемещение моей функции в отдельный файл
Технически мне не нужно было делать, но было много веских причин.
Самое главное, это намного легче загрузить мою функцию в моем тестовом файле.
Поскольку я создаю приложение Vue, я использую .vue
Файловый синтаксис, который не является прямым JavaScript.
Это означает, что мне нужно будет сделать некоторую магию, чтобы сделать мой тестовый файл понять, как загрузить этот компонент Vue, чтобы я мог добраться до кода, который я хотел проверить.
Я не хотел делать ни одно из этого, поэтому вместо этого я просто переместил код в отдельный файл, затем требовал его в моем VUE компонента. Слава благодарность для поддержки модуля в узле/WebPack!
Еще одна веская причина для перемещения функциональности, которую я хотел протестировать, состоит в том, что она заставляет меня удалить любую жесткую интеграцию в Vue, так как это приведет к вам проблемы с моим модульным тестам.
Например, в конце одной из моих функций я назначаю окончательное анализируемое значение для моего VUE-компонента, используя Это. Дата
Отказ
Это была тупая линия кода для меня, чтобы написать, как она смешана в интеграционном коде с функциональным кодом.
Вместо этого я должен просто вернуть это Parseddata
Значение Вернуться к тому, какой код называется его, и пусть он обрабатывает интеграцию. Это будет держать весь мой функциональный код отдельно от остальных, помогая с разделением проблем и такового.
Не написав один тест, я уже улучшил свой код, убирая пару вредных привычек (бросая все в один файл и смешивание проблем в той же функции).
Вот фиксированный файл (мы назовем это doSomething.js
) Чтобы дать вам представление о том, как выглядит мой новый файл:
function doSomething(input) { // do some stuff to input let output = input * 2 // if not right, do it again if (output < 10) { output = doSomething(output) } // some other condition that I need to test if (output > 10 && input === 3) { // here's some strange edge case I need to handle output += ' was 3' } // return the value return output } module.exports = { doSomething }
Создание моего тестового файла
С моим кодом перемещался и немного очищается, теперь я могу начать тестировать его.
Я создал свой тестовый файл в одной папке, что и мой файл функции, так как это сохраняет их рядом, поэтому я помню, что тестовый файл есть.
Чтобы назвать его, я беру как имя, которое я дал свой файл функции и добавил .test
там. Так дано dosomething.js
Я называю свой тестовый файл doSomething.test.js
Отказ
Таким образом, I (и любая используемая я использую) может отличать дифференцировать файлы кодов и тестовых файлов, несмотря на то, что он имеет место рядом друг с другом.
Теперь пришло время накладывать мой тестовый файл.
Первое, что мне нужно сделать, это требуется мой функциональный файл и библиотека Assert. Это легко сделать:
const assert = require('assert'); const { doSomething } = require('./doSomething.js')
С этим я могу написать свой первый тест, который будет простой утверждением, что Досметочное
загружен. Я делаю это, проверяя, что это функция:
const actual = typeof doSomething; assert(actual === "function", `Expected ${actual} to be "function"`); console.log('Test Passed')
Это на самом деле все, что мне нужно сделать, чтобы иметь свой первый тест, написанный и готов бежать.
Если я бегу этот код через Узел doSomthing.test.js
И все хорошо, похоже:
Если бы что-то не так с моим кодом (скажем, я забыл экспортировать эту функцию), утверждение бросит ошибку и выглядит так:
Потому что утверждение бросает ошибку, Консоль
Сообщение никогда не выписано, так как узел останавливается выполнением сразу после выдачи ошибки.
Вот код до сих пор
Простая, эффективная тестовая организация
Я мог бы продолжать писать свои утверждения, как это, но это быстро станет громоздким, плюс, что сообщение об ошибке утверждения, безусловно, является уродливым зверям.
Мне очень хотелось бы назвать свои тесты, то, как я могу получить хорошую организацию, и получите намек на то, что тест проверяется, когда я забуду на следующей неделе (вместе с помощью этого сообщения об ошибке).
Потому что Почти все в JavaScript – это объект Я должен сделать мои тесты объектом тоже!
Я покажу почему через секунду, но вот что я думаю:
const tests = { 'doSomething should be a function' : function () { const actual = typeof doSomething; assert(actual === "function", `Expected ${actual} to be "function"`); } }
Это немного больше кода, но это действительно окупится за секунду.
В этом новом формате мой чек больше не будет работать. Мне нужно называть это в конце моего файла, чтобы сделать магию.
Я мог бы сделать это, бегая Тесты [«Дозметия должны быть функцией»] ()
Но Гоша это раздутое решение.
Вместо этого я могу закрепить свои свойства объекта, выполняя каждую функцию тестирования программно.
Я могу сделать это, получая массив из Тесты
Объект, использующий Объект. Keys Затем, затем зацикливаться через этот массив с foreach Отказ
Object.keys(tests).forEach((test) => { tests[test]() })
Независимо от того, что там происходит, просто продолжайте тестирование
С этим изменением, теперь независимо от того, сколько проверок я пишу, они все будут работать в конце файла без дополнительной работы.
За исключением случаев, если один из них не проходит, то он немедленно остановит исполнение в этот момент.
Что вроде отстой.
Давайте исправить это, используя Попробуйте … Catch Block Отказ
Попробуй ... поймать
Блоки идеально подходят для ситуаций, когда вы запускаете некоторый код (обычно вызывая отдельную функцию), и есть небольшой шанс, что он взорвется.
Вместо того, чтобы иметь дело с Рудом ( быстрые незапланированные разборки ), попробуй ... поймать
Блок позволяет нам обрабатывать ошибку немного более изящно. Это также дает нам возможность продолжать работу оставшегося нашего кода, несмотря на брошенную ошибку.
Чтобы использовать его, мы обертываем функцию, склонную к ошибкам в попробуйте
Блок, затем обрабатывать любые ошибки в нашем поймать
блокировать:
Object.keys(tests).forEach((test) => { try { tests[test]() console.log(`Passed: '${test}'`) } catch (e) { console.error(`Failed: '${test}' - ${e.message}`) } });
Теперь все наши тесты будут работать, даже если один из них терпит неудачу. И мы возвращаем сообщение об успехе вместе с поведением сообщения о состоянии теста.
Вот успешный бег:
И вот неудачный пробег:
И вот обновленный код
Это уверена, что намного приятнее сообщение об ошибке, верно?
Но это не удалось, не должно ли это ничего значит?
Есть эти мелочи называются « Выходные коды «Эти программы используют, чтобы другие программы знали, если они успешно работают или нет.
Они действительно удобны для систем сборки, так как вы можете позволить родительскому процессу знать, что дочерний процесс каким-то образом запутался, позволяя ему прекратить движение вперед и дать вам возможность справиться с проблемой.
В узле, Выходные коды автоматически отправляются под различными условиями , но основные два являются:
0 – ничто не пошло не так, файл завершил бега, как надеялся 1 – неуклюжее фатальное исключение (например, что-то взорвалось)
Когда мы позволяем нашему утверждению взорваться без этого попробуй ... поймать
Блок, Nodejs выйдут с кодом 1, позволяя любому другому процессу знать об этом.
Но когда мы добавили наши попробуй ... поймать
Блок, мы перестали бросать ошибки, а узел начал возвращать код 0 для каждого тестового прогона даже с ошибками.
Эта функциональность выхода кода была довольно хорошей, и было бы действительно круто, имея его обратно.
Ну, мы можем сделать это; Все, что нам нужно сделать, это позвонить узел Process.exit
Функция и пропуск в состоянии, который мы хотим отправить.
Для этого мы определим переменную, установить ее до 0, а затем измените его на 1, если какой-либо из наших тестов не удается. После того, как все тесты запустились, мы отправим эту переменную к Process.exit
Функция, позволяющая узлу знать, что случилось:
let exitCode = 0; Object.keys(tests).forEach((test) => { try { tests[test]() console.log(`Passed: '${test}'`) } catch (e) { exitCode = 1 console.error(`Failed: '${test}' - ${e.message}`) } }) process.exit(exitCode)
Хорошо, это исправляет его для компьютеров, но как насчет нас людей? Мы хотели бы также какой-то намек на статус!
Прямо сейчас все сообщения видят то же самое. Было бы действительно здорово, если бы не ударили тесты, позволяя нам знать, что что-то произошло.
Как мы используем этот код в терминале, мы можем отправить Побегные последовательности В нашем консольном выходе для изменения того, как он отображается.
Есть два, мы захочется:
- Яркий (“\ x1b [1m”), который в основном просто смело
- Сброс («\ x1b [0m»), который сбрасывает форматирование; Важно для тестов, пройденных после неудачи
Мы можем пройти эти коды в нашу «консольные» звонки так же, как мы делаем строки.
Вот что в обновленном Console.Error
Звонок будет:
console.error('\x1b[1m', `Failed: '${test}' - ${e.message}`, '\x1b[0m')
«Яркая» настройка добавляется в начале, то последовательность «сброса» устанавливается в конце, чтобы отключить яркость.
После добавления еще нескольких тестов (целенаправленно не удавающихся), вот как вывод выглядит:
И вот обновленный код
Это даже экономит время?!?
Так что это моя специальная настройка тестирования. Все сказано и сделано, я, вероятно, потратил больше времени, пробуя его вне и писать это, чем я бы потратил, просто наклеив одну из популярных рамх.
Но мне действительно понравилось это упражнение и думать, что это аккуратный подход к простым тестированию подразделения, особенно когда вы не хотите устанавливать какие-либо внешние зависимости.
Также приятно, потому что я могу относиться к тестам, как мало посуды для написания лучшего кода, а не на ходу, чтобы проверить список «настоящего программиста».
И для тех из вас, кто является Addicts Addicts Code, здесь есть значок «100% охвата» для размещения на вашем репо Readme:
Фотография фото Артем Сапегин на Несомненно