Статьи

Расшифровка тестового жаргона

В последнее время мы все больше и больше слышим и читаем о разработке через тестирование. Эта область, однако, поставляется с рядом выражений и специфическим жаргоном, который может сбить с толку новичков. Эта статья проведет вас через наиболее распространенные определения, типы тестов и тестовые части. Будут предоставлены варианты использования и, где возможно, также будет представлен некоторый код на PHP.


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

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

Тестирование программного обеспечения — это практически автоматизированный тест. Автоматизация тестирования существует еще до появления ПК; первые автоматизированные системы тестирования появились во времена мэйнфреймов и консолей. Сегодня автоматизированное тестирование — очевидный путь. Почему? Потому что тестирование — это утомительное и повторяющееся задание — что-то не очень подходящее для людей. Автоматическое тестирование значительно быстрее и точнее, чем ручное тестирование. И нет, это не исключает тестировщика или команду QA из схемы. Это просто заставляет их выполнять более подходящую для человека работу и позволяет им делать это хорошо.

Любой тест должен быть разбит на четыре части:

  • Настройка — все, что нужно подготовить, прежде чем код можно будет запустить
  • Упражнение — запустите код, который мы хотим протестировать
  • Проверить — сравнить результат прогона с некоторым ожидаемым условием
  • Снос — очистите все лишние компоненты, которые мы использовали для тестирования, чтобы система находилась в том же состоянии, в котором она находилась до того, как мы начали текущий тест (состояние до шага установки ).

Мы проектируем каждый тест, чтобы иметь четыре отдельных этапа, которые выполняются в последовательности: настройка прибора, SUT тренировки, проверка результата и демонтаж прибора. Тестовые шаблоны xUnit: рефакторинг тестового кода , автор Gerard Meszaros

Приспособление представляет всю информацию, которая необходима для проведения теста. Приспособление может быть таким же простым, как создание простого объекта, например, $ testObject = new RealObject (); или что-то более сложное, например, заполнение баз данных и запуск пользовательских интерфейсов.

Все, что должна тестировать система (SUT), чтобы мы могли использовать SUT для проверки ее поведения. — Тестовые шаблоны xUnit: рефакторинг тестового кода Gerard Meszaros

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

Что бы мы ни тестировали. SUT всегда определяется с точки зрения теста. Тестовые шаблоны xUnit: рефакторинг тестового кода , автор Gerard Meszaros


Начиная свой второй день на работе, наш программист написал свой первый тест. Это было сложнее, чем он ожидал. Чтобы написать его, ему понадобился каркас тестирования , и он должен был создать тестовый пример, а затем запустить все методы тестирования . Также было несколько странных зависимостей, которые он должен был выяснить. Казалось, что изучение DOC было запланировано.

Среда тестирования — это приложение, специально разработанное для тестирования кода на определенном языке. Концепция тестовой структуры была впервые разработана Кентом Беком в начале 90-х годов. Позже его работа привела к созданию платформы для SmallTalk, которая называется SmalltalkUnit, а затем была переименована в SUnit .

Smalltalk пострадал, потому что ему не хватало культуры тестирования. В этом столбце описывается простая стратегия тестирования и структура для ее поддержки. Стратегия и структура тестирования не предназначены для того, чтобы быть законченными решениями, а скорее отправной точкой, из которой могут быть построены промышленные инструменты и процедуры. Простое тестирование Smalltalk: с паттернами , Кент Бек

Это был первый фреймворк xUnit , и он определил основную концепцию тестирования и термины, представленные выше. Сегодня почти каждый язык программирования предлагает свою версию этой среды: PHPUnit для PHP, JUnit для Java, ShUnit для сценариев оболочки UNIX и так далее. Вы будете удивлены, узнав, сколько вещей можно протестировать сегодня и сколько тестов можно автоматизировать.

Первоначально «контрольный пример» был определен Кентом Беком как наименьшая единица тестирования.

Когда вы разговариваете с тестером, наименьшая единица тестирования, о которой они говорят, это тестовый пример. TestCase — это объект пользователя, представляющий один контрольный пример. Простое тестирование Smalltalk: с использованием паттернов Кента Бека

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

Метод тестирования является самой маленькой частью тестовой архитектуры. Метод тестирования — это блок, состоящий из определенных выше частей: настройка / упражнение / проверка / разборка. Это неотъемлемая часть любого теста; тот, который делает работу.

Метод тестирования — это окончательная процедура, которая дает результат теста. — Руководство по форме и стилю, ASTM, 2012

Это был один из самых запутанных новых терминов для нашего нового программиста. Он представляет все другие классы и системные компоненты, которые нужны нашему SUT для правильной работы. Но также DOC должен предоставить конкретные методы, которые позволяют нам наблюдать и проверять это. Понятия насмешливых и тестовых двойников тесно связаны с DOC.

Отдельный класс или крупнозернистый компонент, от которого зависит тестируемая система (SUT). Зависимость обычно является делегированием через вызовы методов. Тестовые шаблоны xUnit: рефакторинг тестового кода , автор Gerard Meszaros


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

Пирамида тестирования была впервые определена Майком Коном в книге « Успешно завершена гибкая разработка программного обеспечения с использованием Scrum » , а затем вскоре принята сообществом разработчиков программного обеспечения.

Испытательная пирамида

Пирамида представляет три основных уровня тестирования: UI, Service и Unit.

Уровень пользовательского интерфейса представляет собой самый верхний уровень тестирования: когда система работает через пользовательский интерфейс и все приложение тестируется как единое целое. Этот слой должен представлять наименьшее количество в нашем множестве тестов.

Уровень Service содержит несколько разных типов тестов. В основном это касается внутренней связи модулей и правильной работы внешнего API (интерфейса прикладного программирования) приложения. В наших пакетах должно быть несколько таких тестов, но они не должны быть основой для нашего тестирования. Эти тесты обычно тренируют несколько частей приложения, и, следовательно, они довольно медленные. Они должны выполняться как можно чаще, но не при каждом сохранении кода. Вероятно, при каждой сборке системы или при фиксации системы управления версиями.

Уровень « Unit» относится к тестам, выполняющим наименьшие возможные блоки нашего кода в полной изоляции. Эти тесты должны представлять подавляющее большинство тестов. Они должны быть очень быстрыми (1-4 миллисекунды / тест) и должны выполняться как можно чаще. Разработка через тестирование (TDD) является хорошим примером того, как максимально использовать модульные тесты.

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

Детальная Испытательная Пирамида

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

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

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

Тест в этих определениях ссылается на то же, что и тестовый пример.

Тест, который проверяет поведение какой-то небольшой части всей системы. Что превращает тест в модульный тест, так это то, что тестируемая система (SUT) является очень небольшим подмножеством всей системы и может быть неузнаваема для человека, который не участвует в создании программного обеспечения. — Тестовые шаблоны xUnit: рефакторинг тестового кода Gerard Meszaros

Модульные тесты представляют собой подавляющее большинство тестов, которые пишет программист. Да, это правда: модульные тесты чаще всего пишутся программистами. Модульные тесты помогают программистам разрабатывать приложения, предотвращать распространенные ошибки, опечатки и регрессии. Это тесты, сделанные программистами для программистов.

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

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

Компонент является следствием одного или нескольких проектных решений, хотя его поведение также можно проследить до некоторого аспекта требований. — Тестовые шаблоны xUnit: рефакторинг тестового кода Gerard Meszaros

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

Компонент также может быть прослежен до требования или части требования. Это означает, что компонентный тест предназначен не только для программистов. Руководители команд, мастера схваток, архитекторы и другие технически вовлеченные люди, безусловно, заинтересованы в модулях, их организации и иногда даже в их внутренней работе. Эти люди не обязательно знакомы с конкретным языком программирования. Тест должен больше концентрироваться на поведении и определять ожидания более понятным способом.

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

TestFileAccessCanWriteToAFile: Failed asserting that file '/tmp/testfile' is present on the system.

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

Account Administration Test: Failed when we tried to specify 0 (zero) as the total money a user has in his account.

Такой тест обеспечивает более высокий уровень функциональности. Основываясь на приведенном выше сообщении об ошибке, может быть несколько уровней связи и классов / объектов, участвующих в операции определения суммы как суммы в чьем-то счете.

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

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

Другие определяют интеграционные тесты на разных уровнях: все, что определяет связь между двумя элементами, можно рассматривать как интеграцию. Эти элементы могут быть единицами, такими как классы, модули или даже более высокие функциональные части программного обеспечения.

Единого принятого определения термина «интеграционный тест» не существует.

Графический интерфейс приложения взаимодействует с программным обеспечением через программный API. Тестирование на этом уровне требует много кода и может занять относительно много времени.

API — это средство, с помощью которого другое программное обеспечение может вызывать некоторые функции. — Тестовые шаблоны xUnit: рефакторинг тестового кода Gerard Meszaros

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

Архитектура высокого уровня

Обычно эти тесты запускаются периодически и занимают много времени.

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

Проверка, является ли кнопка зеленой или красной или имеет ширину 30 30px , бесполезна и является слишком большой нагрузкой. Так что не спешите проверять свои взгляды. Если что-то пойдет не так с графическим интерфейсом, это будет наблюдаться на этапе предварительного ручного тестирования.

Представления тестирования должны выполнять только две вещи: проверять условное представление и проверять, как называется ожидаемый API.

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

Например, следующий псевдокод является плохим примером для проверки наличия строки на экране.

1
2
3
4
5
function testItCanTellTheNameOfTheUser() {
    // some rendering code logic here
    $renderedName = $this->renderName();
    $this->assertEquals(‘User has the name ‘ . $renderedName[‘first’] . ‘ ‘ . $renderedName[‘last’] . ‘.’);
}

Этот тест не только труден для чтения, но и проверяет точную фразу — что-то вроде «пользователя зовут Джон Доу». включая пунктуацию! Почему это плохо? Потому что кто-то может легко изменить форму этого предложения, не меняя его значения.

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

1
2
3
4
5
6
function testItCanTellTheNameOfTheUser() {
    // some rendering code logic here
    $renderedName = $this->renderName();
    $this->assertRegExp($renderedName[‘first’], $renderedName);
    $this->assertRegExp($renderedName[‘last’], $renderedName);
}

Теперь это гарантирует, что имя присутствует, но его не волнует лексическая конструкция. Кто-то может изменить первоначальную фразу на что-то, например, Дон, Джон — имя текущего пользователя. Смысл останется прежним и тест все равно пройдет правильно!


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

Это один из самых противоречивых тестов. В зависимости от того, какие книги вы читаете, приемочные тесты могут называться функциональными тестами.

или

  • Сквозные тесты
  • или

  • Приемочные испытания
  • или

  • Клиентские тесты.

    Каждое имя происходит от другого сообщества или автора. Я лично предпочитаю приемочные тесты или сквозные тесты .

    Приемочный тест проверяет поведение фрагмента видимой функциональности всей системы. — Тестовые шаблоны xUnit: рефакторинг тестового кода Gerard Meszaros

    Такой тест будет делать что-то на GUI. Изменение произойдет во всей системе. Данные будут сохранены в базе данных или файловой системе. Сетевое общение будет сделано. Наконец, GUI будет проверен на ответ от системы. Такие тесты пытаются полностью имитировать пользователя.

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

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

    Существуют специальные рамки для таких тестов, как Fitness, Selenium, Watir, Cucumber и другие.

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

    Контрактные тесты объясняют, как класс должен расширять суперкласс или реализовывать интерфейс. — Дж. Б. Рейнсбергер

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


    После заслуженного отпуска наш не очень младший программист вернулся на работу. Это был его первый отпуск, и он чувствует себя полным сил для написания тестов и кода. После шести месяцев он чувствует себя довольно хорошо на работе; он хорошо интегрирован в команду, и он пишет действительно хороший код. Но время от времени он испытывает разочарование. Выполнение пяти различных типов тестовых наборов в строго определенном порядке каждый вечер скучно и подвержено ошибкам.

    Затем, есть еще одна странная дискуссия между его руководителем и руководством. Они говорят о CI и CD . Что это может значить? Это было слишком загадочно для нашего нового программиста, чтобы понять. Несколько недель спустя в компании появилось сообщение: «Пожалуйста, больше не проводите вечерние тесты. У нас есть CI!» . Чтобы узнать больше, он пошел к руководителю своей команды и спросил: «Что такое CI и CD?» ,

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

    Непрерывная интеграция — это практика разработки программного обеспечения, при которой члены команды часто интегрируют свою работу, обычно каждый человек интегрируется по крайней мере ежедневно, что приводит к множественным интеграциям в день. Каждая интеграция проверяется автоматизированной сборкой (включая тестирование) для максимально быстрого выявления ошибок интеграции. — Мартин Фаулер

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

    Это связано не столько с тестированием, сколько с КИ. В то время как CI позволяет вам создать систему доставки, релизы по-прежнему выполняются периодически и вручную.

    Непрерывная доставка автоматизирует все этапы от кода к клиенту.

    После того, как все сделано на уровне CI, непрерывная доставка делает еще один шаг вперед и создает установочные комплекты программного обеспечения, публикует их по мере необходимости и даже может запускать процедуры удаленного обновления на клиентах. Цель такой системы — доставить продукт как можно быстрее конечному пользователю. Он сильно зависит от автоматизированных тестов, и, если все они пройдут, продукт доставляется. Период.

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


    Есть части процедуры тестирования, которые просто слишком сложно — если не невозможно — автоматизировать. Вот почему сеанс исследовательского ручного тестирования обычно проводится перед каждым выпуском программного обеспечения. Эти тесты могут быть выполнены специализированными тестировщиками или программистами в зависимости от структуры команды и компании.

    Ручное тестирование предполагает воображение. Люди осматривают систему, гарантируя, что она работает и выглядит так, как нужно.

    Некоторые команды считают ручное тестирование << сломать его, если сможешь! >> Концепция.


    Вы не можете избежать тестирования жаргона. Надеемся, что эта статья пролила некоторый свет на различия между различными формами тестирования. Любые вопросы? Спросите ниже!