Разное

Белый ящик тестирование: Тестирование белого ящика / Хабр

Содержание

Тестирование белого ящика / Хабр

Разработка программ высокого качества подразумевает, что программа и её части подвергаются тестированию. Классическое модульное (unit) тестирование подразумевает разбиение большой программы на маленькие блоки, удобные для тестов. Либо, если разработка тестов происходит параллельно с разработкой кода или тесты разрабатываются до программы (TDD — test driven development), то программа изначально разрабатыватся небольшими блоками, подходящими под требования тестов.

Одной из разновидностей модульного тестирования можно считать propery-based testing (такой подход реализован, например, в библиотеках QuickCheck, ScalaCheck). Этот подход основан на нахождении универсальных свойств, которые должны быть справедливы для любых входных данных. Например, сериализация с последующей десериализацией должна давать такой же объект. Или, повторная сортировка не должна менять порядок элементов в списке. Для проверки таких универсальных свойств в вышеупомянутых библиотеках поддерживается механизм генерации случайных входных данных. Особенно хорошо такой подход работает для программ, основанных на математических законах, которые служат универсальными свойствами, справедливыми для широкого класса программ. Есть даже библиотека готовых математических свойств — discipline — позволяющая проверить выполнение этих свойств в новых программах (хороший пример повторного использования тестов).

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

Под катом описаны несколько подходов к тестированию сложных программ с одним входом с разной степенью сложности (вовлеченности) и разной степенью покрытия.

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

Тестовый стенд (test bench)

Прежде всего, так как тестируется всего одна функция, код вызова которой всегда одинаков, то у нас нет необходимости создавать отдельные unit test’ы. Все такие тесты были бы одинаковыми с точностью до входных данных и проверок. Вполне достаточно в цикле передавать исходные данные (input) и проверять результаты (expectedOutput). Чтобы в случае обнаружения ошибки можно было идентифицировать проблемный набор тестовых данных, все тестовые данные надо снабдить меткой (label). Таким образом, один набор тестовых данных можно представить в виде тройки:

case class TestCase[A, B](label: String, input: A, expectedOutput: B)

Результат одного прогона можно представить в виде TestCaseResult:

case class TestCaseResult[A, B](testCase: TestCase[A, B], actualOutput: Try[B])

(Результат запуска мы представляем с помощью Try, чтобы захватить возможные исключения.)

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

def runTestCases[A, B](cases: Seq[TestCase[A, B])(f: A => B): Seq[TestCaseResult[A, B]] = 
  cases
    .map{ testCase => 
      TestCaseResult(testCase, 
        Try{ f(testCase.input) }
      ) 
    }
    .filter(r => r.actualOutput != Success(r.testCase.expectedOutput))

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

Для удобства можно отформатировать результаты тестирования

def report(results: Seq[TestCaseResult[_, _]]): String = 
  s"Failed ${results.length}:\n" + 
    results
      .map(r => r.testCase.label + ": expected " + r.testCase.expectedOutput + ", but got " + r.actualOutput)
      .mkString("\n")

и выводить отчёт только в случае ошибок:

val testCases = Seq(
  TestCase("1", 0, 0)
)

test("all test cases"){
  val testBench = runTestCases(testCases) _
  val results = testBench(f)
  assert(results.isEmpty, report(results))
}

Подготовка входных данных

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

val baseline = MyObject(...) // входной объект можно создать вручную или сгенерировать
val testCases = Seq(
  TestCase("baseline", baseline, ???),
  TestCase("baseline + (field1 = 123)", baseline.copy(field1 = "123"), ???)
)

При работе со вложенными неизменяемыми структурами данных большим подспорьем являются линзы, например, из библиотеки Monocle:

val baseline = ??? 
val testObject1 = (field1 composeLens field2).set("123")(baseline)
// что эквивалентно следующей строке:
val testObject1 = baseline.copy(field1 = baseline.field1.copy(field2 = "123"))

Линзы позволяют элегантно «модифицировать» глубоко вложенные части структур данных: Каждая линза представляет собой getter и setter для одного свойства. Линзы можно соединять и получать линзы, «фокусирующиеся» на следующем уровне.

Использование DSL для представления изменений

Далее будем рассматривать формирование тестовых данных путём внесения изменений в некоторый исходный входной объект. Обычно для получения нужного нам тестового объекта требуется внести несколько изменений. При этом весьма полезно в текстовое описание TestCase’а включить перечень изменений:

val testCases = Seq(
  TestCase("baseline", baseline, ???),
  TestCase("baseline + " + 
              "(field1 = 123) + " +  // описание 1-го изменения
              "(field2 = 456) + " +  // 2-го
              "(field3 = 789)",      // 3-го
           baseline
             .copy(field1 = "123")   // 1-е изменение
             .copy(field2 = "456")   // 2-е изменение
             .copy(field3 = "789"),  // 3-е изменение
           ???)
)

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

Чтобы текстовый перечень изменений не расходился с фактическими изменениями, необходимо следовать принципу «единой версии правды». (Если одна и та же информация требуется/используется в нескольких точках, то следует иметь единственный первичный источник уникальной информации, а во все остальные точки использования информация должны распространяться автоматически, с необходимыми преобразованиями. Если этот принцип нарушать, и копировать информацию вручную, то неизбежно расхождение версий информации в разных точках. То есть в описании тестовых данных мы увидем одно, а в тестовые данных — другое. Например, копируя изменение field2 = "456" и корректируя его в field3 = "789" мы можем случайно забыть исправить описание. В итоге описание будет отражать только два изменения из трёх.)

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

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

Модель изменений должна позволять решать следующие задачи:

  1. Порождение экземпляров модели изменений. (То есть фактически создание конкретного списка изменений.)
  2. Формирование текстового описания изменений.
  3. Применение изменений к объектам предметной области.
  4. Выполнение оптимизационных преобразований над моделью.

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

Другим способом формирования экземпляров модели изменений может служить специализированный язык (DSL), создающий объекты моделей изменения с помощью набора extension-методов и вспомогательных операторов. Ну а в простейших случаях экземпляры модели изменений можно создавать непосредственно, через конструкторы.

Подробности языка изменений

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

  1. Модель структуры данных.
  2. Модель изменений.
  3. Собственно Embedded(?) DSL — вспомогательные конструкции, extension-методы, для удобного конструирования изменений.
  4. Интерпретатор изменений, позволяющий фактически «модифицировать» объект (на самом деле, естественно, создать изменённую копию).

Приведём пример программы, записанной с использованием DSL:

val target: Entity[Target] // объект, в который вносятся изменения
val updateField1 = target \ field1 := "123"
val updateField2 = target \ subobject \ field2 := "456"
// или, без использования DSL:
val updateField1 = SetProperty(PropertyAccess(target, Property(field1, typeTag[String])), LiftedString("123"))
val updateField2 = SetProperty(PropertyAccess(PropertyAccess(target, 
                    Property(subobject, typeTag[SubObject])), 
                      Property(field2, typeTag[String])), LiftedString("456"))

То есть с помощью extension-методов \ и := формируются объекты PropertyAccess, SetProperty из ранее созданных объектов target, field1, subobject, field2. Также за счёт (опасных) implicit-конвертаций строка «123» упаковывается в LiftedString (можно обойтись без implicit-конвертаций и вызвать соответствующий метод явно: lift("123")).

В качестве модели данных может быть использована типизированная онтология (см. https://habr.com/post/229035/ и https://habr.com/post/222553/). (Вкратце: объявляются объекты-имена, представляющие свойства какого-либо типа предметной области: val field1: Property[Target, String].) При этом собственно данные могут храниться, например, в виде JSON. Удобство типизированной онтологии в нашем случае заключается в том, что модель изменений обычно оперирует отдельными свойствами объектов, а онтология как раз даёт подходящий инструмент для адресации свойств.

Для представления изменений необходим набор классов того же плана, что и вышеприведённый класс SetProperty:

  • Modify — применение функции,
  • Changes — применение нескольких изменений последовательно,
  • ForEach — применение изменений к каждому элементу коллекции,
  • и т.д.

Интерпретатор языка изменений представляет собой обычный рекурсивный вычислитель выражений, основанный на PatternMatching’е. Что-то наподобие:

def eval(expression: DslExpression, gamma: Map[String, Any]): Any = expression match {
  case LiftedString(str) =>
    str
  case PropertyAccess(obj, prop) =>
    Getter(prop)(gamma).get(obj)
}
def change[T] (expression: DslChangeExpression, gamma: Map[String, Any], target: T): T = expression match {
  case SetProperty(path, valueExpr) =>
    val value = eval(valueExpr, gamma)
    Setter(path)(gamma).set(value)(target)
}

Для непосредственного оперирования свойствами объектов необходимо для каждого свойства, используемого в модели изменений, задать getter и setter. Этого можно достичь, заполнив отображение (Map) между онтологическими свойствами и соответствующими им линзами.

Такой подход в целом работает, и действительно позволяет описывать изменения один раз, однако постепенно появляется потребность представлять всё более сложные изменения и модель изменений несколько разрастается. Например, если необходимо изменить какое-то свойство с использованием значения другого свойства того же объекта (например, field1 = field2 + 1), то возникает необходимость в поддержки переменных на уровне DSL. А если изменение свойства нетривиально, то на уровне DSL потребуется поддержка арифметических выражений и функций.

Тестирование ветвей

Тестируемый код может быть линейным, и тогда нам по большому счёту достаточно одного набора тестовых данных, чтобы понять, работает ли он. В случае наличия ветвления (if-then-else), необходимо запускать белый ящик как минимум дважды с разными входными данными, чтобы были исполнены обе ветки. Количество наборов входных данных, достаточных для покрытия всех ветвей, по-видимому, численно равно цикломатической сложности кода с ветвлениями.

Как сформировать все наборы входных данных? Так как мы имеем дело с белым ящиком, то мы можем вычленить условия ветвления и дважды модифицировать входной объект так, чтобы в одном случае выполнялась одна ветвь, в другом случае — другая. Рассмотрим пример:

if (object.field1 == "123") A else B

Имея такое условие, мы можем сформировать два тестовых случая:

val testCase1 = TestCase("A", field1.set("123")(baseline), /* result of A */)
val testCase2 = TestCase("B", field1.set(/* не "123", а, например, */"123" + "1">)(baseline), /*result of B*/)

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

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

DSL для формирования всех комбинаций изменений

Рассмотрим подробнее механизм, позволяющий сформировать все возможные перечни изменений, обеспечивающие полное покрытие всех ветвлений. Для того, чтобы использовать перечень изменений при тестировании, нам надо все изменения объединить в один объект, который мы подадим на вход тестируемого кода, то есть требуется поддержка композиции. Для этого можно либо воспользоваться вышеприведённым DSL для моделирования изменений, и тогда достаточно простого списка изменений, либо представить одно изменение в виде функции модификации T => T:

val change1: T => T = field1.set("123")(_)
// val change1: T => T = _.copy(field1 = "123")
val change2: T => T = field2.set("456")

тогда цепочка изменений будет представлять собой просто композицию функций:

val changes = change1 compose change2

или, для списка изменений:

val rawChangesList: Seq[T => T] = Seq(change1, change2)
val allChanges: T => T = rawChangesList.foldLeft(identity)(_ compose _)

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

val tests: Seq[(String, T => T)] =
           IF("field1 == '123'")  // название условия, которое мы моделируем
           THEN( field1.set("123"))( // или target \ field1 := "123"
             IF("field2 == '456')
             THEN(field2.set("456"))(TERMINATE)
             ELSE(field2.set("456" + "1"))(TERMINATE)
           )
           ELSE( field1.set("123" + "1") )(TERMINATE)

Здесь коллекция tests содержит агрегированные изменения, соответствующие всем возможным комбинациям ветвей. Параметр типа String будет содержать все названия условий и все описания изменений, из которых сформирована агрегированная функция изменений. А второй элемент пары типа T => T — как раз агрегированная функция изменений, полученная в результате композиции отдельных изменений.

Чтобы получить изменённые объекты, надо все агрегированные функции изменений применить к baseline-объекту:

val tests2: Seq[(String, T)] = tests.map(_.map_2(_(baseline)))

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

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

Автоматическое формирование тестовых данных

Так как мы имеем дело с белым ящиком, то можем видеть все ветвления. Это даёт возможность построения модели логики, содержащейся в белом ящике, и использования модели для генерации тестовых данных. В случае, если тестируемый код написан на Scala, можно, например, использовать scalameta для чтения кода, с последующем преобразованием в модель логики. Опять же, как и в рассмотренном ранее вопросе моделирования логики изменений, для нас затруднительно моделирование всех возможностей универсального языка. Далее будем предполагать, что тестируемый код реализован с использованием ограниченного подмножества языка, либо на другом языке или DSL, который изначально ограничен. Это позволяет сосредоточиться на тех аспектах языка, которые представляют для нас интерес.

Рассмотрим пример кода, содержащего единственное ветвление:

if(object.field1 == "123") A else B

Условие разбивает множество значений поля field1 на два класса эквивалентности: == "123" и != "123". Тем самым, всё множество входных данных также разбивается на два класса эквивалентности по отношению к этому условию — ClassCondition1IsTrue и ClassCondition1IsFalse. С точки зрения полноты покрытия нам достаточно взять хотя бы по одному примеру из этих двух классов, чтобы покрыть обе ветви A и B. Для первого класса мы можем построить пример, в каком-то смысле, единственным образом: взять случайный объект, но изменить поле field1 на "123". При этом объект обязательно окажется в классе эквивалентности ClassCondition1IsTrue и вычисления пойдут по ветви A. Для второго класса примеров больше. Один из способов генерации какого-то примера второго класса: генерировать произвольные входные объекты и отбрасывать такие, у которых field1 == "123". Ещё один способ: взять случайный объект, но изменить поле field1 на "123" + "*" (для модификации можно использовать любое изменение контрольной строки, гарантирующее, что новая строка не равна контрольной).

В качестве генераторов случайных данных вполне подходит механизм генераторов Arbitrary и Gen из библиотеки ScalaCheck.

По-сути, мы выполняем обращение булевой функции, используемой в операторе if. То есть находим все значения входного объекта, для которых эта булева функция принимает значение trueClassCondition1IsTrue, и все значения входного объекта, для которых она принимает значение falseClassCondition1IsFalse.

Подобным образом можно генерировать данные, подходящие под ограничения, порождаемые простыми условными операторами с константами (больше/меньше константы, входит во множество, начинается с константы). Такие условия нетрудно обратить. Даже если в тестируемом коде вызываются несложные функции, то мы можем заменить их вызов на их определение (inline) и всё-таки осуществить обращение условных выражений.

Трудно обратимые функции

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

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

if(sha(object.field1)=="a9403...") ...
// после введения дополнительного параметра ==> 
if(object.sha_field1 == "a9403...") ...

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

При таких манипуляциях мы заменяем (подменяем) объект тестирования. Тем не менее, в каком-то смысле новая построенная программа включает логику прежней программы. Действительно, если в качестве значений новых искуственных параметров взять результаты вычисления функций, которые мы заменили на параметры, то программа выдаст те же самые результаты. По-видимому, тестирование изменённой программы по-прежнему может представлять интерес. Надо лишь помнить, при каких условиях изменённая программа будет вести себя также, как исходная.

Зависимые условия

Если ветвления в коде опираются на независимые поля объекта, то задача полного покрытия решается прямолинейно. Достаточно записать все подмножества для каждого тестируемого поля, а затем, используя подходящие генераторы, сгенерировать новые значения для всех полей. Если же последующие условия уточняют множество значений поля, то необходимо брать пересечение подмножеств. (Например, первое условие, x > 0, а следующее — x <= 1. Каждое из условий могло бы дать по два подмножества, но за счёт пересечений в итоге получится только три подмножества — (-∞, 0], (0, 1], (1, +∞), — примеры из которых надо будет сгенерировать.)

Если при формировании уточняющих множеств мы обнаружим, что одно из подмножеств пусто, то это означает, что условие всегда будет принимать фиксированное значение true или false вне зависимости от входных значений. Поэтому соответствующая ветка, которая никогда не вызывается, является «мертвым кодом» и может быть удалена из кода вместе с условием.

Связанные параметры

Рассмотрим случай, когда условие ветвления основано на двух полях объекта, также связанных условиями:

if(x > 0)
  if(y > 0)
   if (y > x)

(Здесь каждое из полей ограничено > 0, и оба поля совместно тоже ограничены — y > x.)

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

В случае, если условие «жёсткое», функциональное (y == x + 1), то можно построить функцию, вычисляющую значение второго поля на основе сгенерированного первого.

Если условие «полужесткое» (y > x + 1 && y < x + 2), то можно построить зависимый генератор, диапазон значений которого определяется сгенерированным значением первого поля.

Символьное выполнение

Для того, чтобы собрать все условия, порождающие результат по какой-либо из ветвей, можно воспользоваться «cимвольным выполнением» (Symbolic Execution, Символьное выполнение программ), суть которого заключается в следующем. Входные данные принимаются равными некоторым символьным значениям (field1 = field1_initial_value). Затем над символьными значениями производятся все манипуляции, описанные в тестируемом коде. Все манипуляции выполняются в символьном же виде:

val a = field1 + 10
// добавляем в контекст a = field_initial_value + 10
val b = a * 3
// добавляем в контекст b = 3 * field_initial_value + 30

Для обработки ветвления принимаются возможными оба варианта условия — true и false. И расчёт производится сразу для двух веток. При этом на символьные значения в каждой ветке накладываются противоположные ограничения. Например,

if(a > 0) A else B
// в ветке A принимаем, что field_initial_value + 10  > 0
// в ветке B принимаем, что field_initial_value + 10 <= 0

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

Тестирование циклов и рекурсивных функций

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

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

Воспользуемся такой конструкцией как Y-комбинатор («комбинатор неподвижной точки», stackoverflow:What is a Y-combinator? (2-ой ответ), habr: Получение Y-комбинатора в 7 простых шагов). Комбинатор позволяет реализовать рекурсию в языках, которые рекурсию в чистом виде не поддерживают. (Сам комбинатор является рекурсивным, поэтому должен быть реализован на языке, поддерживающем рекурсию.) Работает он следующим образом. Из рекурсивной функции удаляются все рекурсивные вызовы и заменяются на вызовы функции, которая передаётся в качестве дополнительного аргумента. Такая переработанная функция уже не будет являться рекурсивной, а служит только «заготовкой» для получения целевой функции. Y-комбинатор превращает такую «заготовку рекурсивной функции» в полноценную рекурсивную функцию (передавая в качестве аргумента собственное продолжение).

Рассмотрим вначале важный частный случай хвостовой рекурсии (Хвостовая рекурсия). Перепишем тестируемый код, заменив рекурсивные вызовы на вызовы вспомогательной функции. Для целей тестирования мы передадим собственную реализацию вспомогательной функции, которая не будет формировать рекурсию. Такая вспомогательная функция может формировать возвращаемый результат, соответствующий типу возвращаемых значений белого ящика. Например, если возвращаются строки, то вспомогательная функция также будет формировать строку, которую мы сможем проверить в рамках TestCase‘а. В случае, если тип возвращаемых значений нам окажется неудобен, мы можем выбрасывать исключение (throw имеет тип Nothing или bottom, являющийся подтипом всех остальных). Тем самым мы получим возможность тестирования кода без циклов и риска зависания.

В случае общей рекурсии рекурсивный вызов возвращает результат, который затем используется. В этом случае вышеприведённый подход напрямую не работает. Можно попробовать применить подход, аналогичный тому, что мы использовали для вызовов трудно обратимых функций. А именно, заменим каждый рекурсивный вызов на новый параметр. Значение этих параметров можно будет генерировать как обычно, исходя из условий ветвлений, в которых эти параметры используются. Как и в случае с заменой вызовов функций на параметры, результаты, которые мы будем получать, могут отличаться от результатов, которые мы можем получить в действительности. Совпадение будет достигаться в том случае, если значение параметра совпадает со значением рекурсивной функции. Такой подход позволяет нам протестировать шаги, выполняемые после рекурсивного вызова.

Смысл тестирования белого ящика

При определённом усердии можно добиться того, что тесты, написанные вручную или сгенерированные автоматически, будут покрывать все ветви тестируемого кода, то есть обеспечат 100% покрытие. Тем самым мы сможем с уверенностью сказать, что белый ящик делает то, что он делает. Хм. Секундочку. А в чём, собственно, смысл такого тестирования, спросит внимательный читатель? Ведь для любого содержимого белого ящика будут построены тесты, которые только лишь подтверждают, что белый ящик работает каким-то определённым образом.

В некоторых случаях такой набор тестов всё же может иметь смысл:

  1. Если белый ящик является прототипом и существует ненулевая вероятность ошибки для действительной реализации в другой среде.
  2. Если существует несколько реализаций одинаковой логики (на разных языках или в разных окружениях).
  3. Код белого ящика эволюционирует или подвергается рефакторингу, при этом мы хотели бы обнаруживать отличия от эталонного поведения.
  4. Мы хотим обнаружить подмножества входных данных, обеспечивающие требуемые нам результаты.

Следует иметь в виду некоторые особенности тестирования, основанного на реализации, в отличие от тестирования на основе спецификации. Во-первых, если изначальная реализация не поддерживала некоторую функциональность, которую можно было бы ожидать, основываясь на спецификации, то наши тесты не заметят её отсутствия. Во-вторых, если такая функциональность присутствовала, но работала иначе, чем указано в спецификации (то есть, с ошибками), то наши тесты не просто этих ошибок не обнаружат, а напротив, ошибки будут «кодифицированы» в тестах. И если последующие/альтернативные реализации попробуют исправить ошибки, то такие тесты не позволят этого просто так сделать.

Заключение

Тестирование белого ящика смещает акцент с вопроса «что должен делать код» на «что фактически делает код». Иными словами, вместо использования более высокого уровня абстракции, формирования тестов на основе спецификации, используется точно тот же уровень абстракции, что и при реализации кода. Мы можем получить хорошие результаты в плане покрытия кода, но при этом такое тестирование имеет смысл в ограниченном наборе случаев.

Если вы столкнулись с таким случаем, в котором тестирование белого ящика оправдано, то соображения, приведённые выше, могут пригодиться. Во-первых, основные усилия имеет смысл сосредоточить на формировании тестовых наборов данных, так как вход у белого ящика один (вызов функции), а протестировать хотелось бы все ветви. Во-вторых, по-видимому, имеет смысл построить модель тестируемого кода. Для этого может использоваться специализированный DSL, достаточно выразительный, чтобы представлять тестируемую логику. В-третьих, пользуясь моделью тестируемой логики можно попробовать автоматически сформировать тестовые данные, покрывающие все ветви. В-четвертых, тестируемый код может быть подвергнут автоматическим преобразованиям, которые делают его более удобным для тестирования (исключение вызовов труднообратимых функций, переход от циклов к рекурсии, исключение рекурсивных вызовов). При использовании этих подходов можно получить хорошие результаты в плане покрытия кода.

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

Благодарности

Хотелось бы поблагодарить @mneychev за терпение и неоценимую помощь при подготовке статьи.

Тестирование белого ящика — CoderLessons.com

Что такое тестирование белого ящика?

WHITE BOX TESTING — это тестирование внутренней структуры, дизайна и кодирования программного решения. В этом типе тестирования код виден тестеру. Основное внимание уделяется проверке потока входных и выходных данных через приложение, улучшению дизайна и удобства использования, усилению безопасности. Тестирование белого ящика также известно как тестирование Clear Box, тестирование Open Box, структурное тестирование, тестирование прозрачного бокса, тестирование на основе кода и тестирование Glass Box. Это обычно выполняется разработчиками.

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

Термин «WhiteBox» был использован из-за концепции прозрачной коробки. Ясное поле или имя WhiteBox символизирует способность видеть сквозь внешнюю оболочку программного обеспечения (или «коробку») в его внутренней работе. Аналогично, «черный ящик» в « Тестировании черного ящика » символизирует невозможность увидеть внутреннюю работу программного обеспечения, так что может быть протестирован только опыт конечного пользователя.

В этом уроке вы узнаете

Что вы проверяете в White Box Testing?

Тестирование белого ящика включает тестирование программного кода для следующего:

  • Внутренние дыры в безопасности
  • Сломанные или плохо структурированные пути в процессах кодирования
  • Поток конкретных входов через код
  • Ожидаемый результат
  • Функциональность условных циклов
  • Тестирование каждого оператора, объекта и функции на индивидуальной основе

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

Нажмите здесь, если видео не доступно

Как вы проводите тестирование белого ящика?

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

ШАГ 1) ПОНИМАТЬ ИСТОЧНИК КОД

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

Шаг 2) СОЗДАТЬ ИСПЫТАТЕЛЬНЫЕ ДЕЛА И ИСПОЛНИТЬ

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

Пример тестирования WhiteBox

Рассмотрим следующий фрагмент кода

Printme (int a, int b) {                       ------------  Printme is a function 
    int result = a+ b; 
    If (result> 0)
    	Print ("Positive", result)
    Else
    	Print ("Negative", result)
    }                                        -----------   End of the source code 

Целью тестирования WhiteBox является проверка всех ветвей решений, циклов, операторов в коде.

Чтобы выполнить утверждения в приведенном выше коде, тестовые случаи WhiteBox будут

  • A = 1, B = 1
  • А = -1, В = -3

Методы испытаний белой коробки

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

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

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

Покрытие ветвления — этот метод проверяет все возможные пути (если-еще и другие условные циклы) программного приложения.

Помимо вышесказанного, существует множество типов покрытия, таких как покрытие условий, покрытие нескольких условий, покрытие пути, покрытие функций и т. Д. Каждый метод имеет свои преимущества и пытается протестировать (охватить) все части программного кода. Используя покрытие Statement и Branch, вы обычно достигаете 80-90% покрытия кода, что является достаточным.

Чтобы узнать более подробно, обратитесь к этой статье https://www.guru99.com/code-coverage.html

Типы тестирования белого ящика

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

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

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

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

  • Тестирование проникновения в White Box : В этом тестировании тестировщик / разработчик имеет полную информацию об исходном коде приложения, подробную информацию о сети, задействованные IP-адреса и всю информацию о сервере, на котором работает приложение. Цель состоит в том, чтобы атаковать код с нескольких сторон, чтобы выявить угрозы безопасности.
  • Тестирование мутации White Box : Тестирование мутации часто используется, чтобы обнаружить лучшие методы кодирования, используемые для расширения программного решения.

Инструменты тестирования White Box

Ниже приведен список лучших инструментов тестирования белого ящика.

Преимущества тестирования белого ящика

  • Оптимизация кода путем поиска скрытых ошибок.
  • Тестовые случаи «белого ящика» могут быть легко автоматизированы.
  • Тестирование является более тщательным, поскольку обычно покрываются все пути кода.
  • Тестирование может начаться рано в SDLC, даже если GUI недоступен.

Недостатки тестирования WhiteBox

  • Тестирование белого ящика может быть довольно сложным и дорогостоящим.
  • Разработчики, которые обычно выполняют тесты «белого ящика», ненавидят это. Тестирование белого ящика разработчиками не детально может привести к производственным ошибкам.
  • Тестирование белого ящика требует профессиональных ресурсов с подробным пониманием программирования и реализации.
  • Тестирование белого ящика отнимает много времени, более крупные приложения для программирования требуют времени для полного тестирования.

Конечные заметки:

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

 

White/Black/Grey Box-тестирование — QALight

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

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

Black Box

Summary: Мы не знаем, как устроена тестируемая система.

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

Согласно ISTQB:

тестирование черного ящика – это:

– тестирование, как функциональное, так и нефункциональное, не предполагающее знания внутреннего устройства компонента или системы.

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

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

– неправильно реализованные или недостающие функции;

– ошибки интерфейса;

– ошибки в структурах данных или организации доступа к внешним базам данных;

– ошибки поведения или недостаточная производительности системы;

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

Пример:

Тестировщик проводит тестирование веб-сайта, не зная особенностей его реализации, используя только предусмотренные разработчиком поля ввода и кнопки. Источник ожидаемого результата – спецификация.

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

Техника черного ящика применима на всех уровнях тестирования (от модульного до приемочного), для которых существует спецификация. Например, при осуществлении системного или интеграционного тестирования, требования или функциональная спецификация будут основой для написания тест-кейсов.

Техники тест-дизайна, основанные на использования черного ящика, включают:

– классы эквивалентности;

– анализ граничных значений;

– таблицы решений;

– диаграммы изменения состояния;

– тестирование всех пар.

Преимущества:

– тестирование производится с позиции конечного пользователя и может помочь обнаружить неточности и противоречия в спецификации;

– тестировщику нет необходимости знать языки программирования и углубляться в особенности реализации программы;

– тестирование может производиться специалистами, независимыми от отдела разработки, что помогает избежать предвзятого отношения;

– можно начинать писать тест-кейсы, как только готова спецификация.

Недостатки:

– тестируется только очень ограниченное количество путей выполнения программы;

– без четкой спецификации (а это скорее реальность на многих проектах) достаточно трудно составить эффективные тест-кейсы;

– некоторые тесты могут оказаться избыточными, если они уже были проведены разработчиком на уровне модульного тестирования;

Противоположностью техники черного ящика является тестирование методом белого ящика, речь о котором пойдет ниже.

 

White Box

Summary: Нам известны все детали реализации тестируемой программы.

Тестирование методом белого ящика (также: прозрачного, открытого, стеклянного ящика; основанное на коде или структурное тестирование) – метод тестирования программного обеспечения, который предполагает, что внутренняя структура/устройство/реализация системы известны тестировщику. Мы выбираем входные значения, основываясь на знании кода, который будет их обрабатывать. Точно так же мы знаем, каким должен быть результат этой обработки. Знание всех особенностей тестируемой программы и ее реализации – обязательны для этой техники. Тестирование белого ящика – углубление во внутренне устройство системы, за пределы ее внешних интерфейсов.

Согласно ISTQB:

тестирование белого ящика – это:

– тестирование, основанное на анализе внутренней структуры компонента или системы.

– тест-дизайн, основанный на технике белого ящика – процедура написания или выбора тест-кейсов на основе анализа внутреннего устройства системы или компонента.

Почему «белый ящик»? Тестируемая программа для тестировщика – прозрачный ящик, содержимое которого он прекрасно видит.

Пример:

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

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

Техника белого ящика применима на разных уровнях тестирования – от модульного до системного, но главным образом применяется именно для реализации модульного тестирования компонента его автором.

Преимущества:

– тестирование может производиться на ранних этапах: нет необходимости ждать создания пользовательского интерфейса;

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

Недостатки:

– для выполнения тестирования белого ящика необходимо большое количество специальных знаний

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

Сравнение Black Box и White Box

Grey Box

 

Summary: Нам известны только некоторые особенности реализации тестируемой системы.

Тестирование методом серого ящика – метод тестирования программного обеспечения, который предполагает, комбинацию White Box и Black Box подходов. То есть, внутреннее устройство программы нам известно лишь частично. Предполагается, например, доступ к внутренней структуре и алгоритмам работы ПО для написания максимально эффективных тест-кейсов, но само тестирование проводится с помощью техники черного ящика, то есть, с позиции пользователя.

Эту технику тестирования также называют методом полупрозрачного ящика: что-то мы видим, а что-то – нет.

Пример:

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

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

Тестирование белого ящика (white box testing)

Подробности




марта 30, 2016



Обновлено: 04 апреля 2016



Просмотров: 29421


В стратегии White Box (белый ящик) тестирования рассматривается внутренняя логика и структура кода. Его также называют стеклянным, структурным, открытым или прозрачным ящиком тестирования. Тесты, написанные на основе стратегии White Box тестирования включают покрытие написанного кода, ответвлений, путей, отчетности, внутренней логики кода и др.

В целях реализации метода тестирования белого ящика, тестировщик имеет дело с кодом, и, следовательно, ему необходимо владеть знаниями кодирования и логики т. е., внутренней работы кода. White Box тест также нужен в тестировщике, который взглянув на код может выяснить, какой блок/кусок кода работает неправильно.

 

Направления использования White Box тестирования

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

Участки кода, которые тестируются с помощью White Box тестирования являются:

  • Покрытие кода
  • Строковое покрытие
  • Покрытие решений
  • Покрытие условий
  • Циклы
  • Пути
  • Покрытие потока данных

 

Есть три аспекта кодекса, которые проверяются в White Box тестировании, а именно:

  • Было ли программное обеспечение разработано в соответствии с оригинальным дизайном программного обеспечения.
  • Были ли внедрены меры безопасности в программное обеспечение и надежны ли они.
  • Выяснить уязвимости указанного программного обеспечения.

 

Преимущества White Box тестирования

  • Знание структуры внутреннего кодирования является предпосылкой при которой становится очень легко выяснить, какой тип ввода или какие данные могут помочь в эффективном тестировании приложений.
  • Еще одно преимущество White Box тестирования заключается в том, что оно помогает в оптимизации кода.
  • Помогает в удалении дополнительных строк кода, которые могут производить дефекты в коде.

 

Недостатки White Box тестирования

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

 

Виды испытаний White/Glass Box тестирования

 

Модульное тестирование

Разработчик выполняет модульное тестирование, чтобы проверить, правильно ли работает конкретный модуль или блок кода. Модульное тестирование происходит на самом базовом уровне и осуществляется при разработке конкретного модуля или при встраивании определенной функции.

 

Статический и динамический анализ

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

 

Строковое покрытие

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

 

Покрытие решений

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

 

Тестирование утечки памяти

Когда код написан, есть вероятность, что в коде существует проблема утечки памяти, которая делает код неисправным. Поэтому, во время тестирования по методу белого ящика проверяется есть ли в коде утечка памяти. В случае утечки памяти, для программного обеспечения требуется больше памяти, и это влияет на скорость работы программного обеспечения, что делает его медленным.

 

Тестирование безопасности

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

 

Мутационное тестирование

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

 

Кроме всех тех видов тестирования, которые приведенные выше, есть еще несколько типов, которые подпадают под оба вида стратегий тестирования черного и белого ящика, такие как: функциональное тестирование (что касается кода с целью проверки его эксплуатационных качеств), инкрементное тестирование интеграции (которая занимается тестированием добавленного в приложение кода), тестирование производительности и нагрузки (которая помогает выяснить, как тот или иной код управляет ресурсами и дает производительность) и др. Поскольку они подпадают под White Box, а также под Black Box трудно классифицировать их в любой из этих двух широких типов тестирования программного обеспечения.

Читайте также

 

 

 

 

Тестирование методом «белого ящика» — IT-Курсы в Минске

Что такое тестирование методом «белого ящика»?

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

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

Виды тестирований методом «белого ящика»:

Модульное тестирование:

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

Статический и динамический анализ:

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

Покрытие операторов:

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

Покрытие ветвей:

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

Тестирование защищенности:

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

Тестирование мутаций:

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

Помимо всех видов тестирования, приведенных выше, есть еще несколько видов, которые подпадают под тестирования методами черного и белого ящиков, такие как: функциональное тестирование (которое касается кода для проверки его функциональной производительности), инкрементное интеграционное тестирование ( тестирование недавно добавленного кода в приложении), тестирование производительности и нагрузок (которое помогает определить, как конкретный код управляет ресурсами и дает производительность и т. д.). Кстати, наши курсы Тестирования ПО в Минске тщательно разбирают этот вопрос – рекомендуем записаться прямо сейчас.

Преимущества тестирования методом белого ящика:

  • Поскольку знание внутренней структуры кодирования является предпосылкой, становится очень легко выяснить, какой тип ввода / данных может помочь в эффективном тестировании приложения.
  • Другим преимуществом тестирования белого ящика является то, что он помогает оптимизировать код
  • Это помогает в устранении дополнительных строк кода, которые могут привести к скрытым дефектам.

Недостатками тестирования методом белого ящика являются:

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

Запишитесь на наши курсы Тестирования ПО в Минске прямо сейчас или закажите звонок с бесплатной консультацией!

Записаться сейчас / Бесплатная консультация

White/Black/Grey Box-тестирование | BUGZA

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

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

Black Box

Summary: Мы не знаем, как устроена тестируемая система.

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

Согласно ISTQB, тестирование черного ящика – это:

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

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

  • неправильно реализованные или недостающие функции;
  • ошибки интерфейса;
  • ошибки в структурах данных или организации доступа к внешним базам данных;
  • ошибки поведения или недостаточная производительности системы;

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

Пример:

Тестировщик проводит тестирование веб-сайта, не зная особенностей его реализации, используя только предусмотренные разработчиком поля ввода и кнопки. Источник ожидаемого результата – спецификация.

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

Техника черного ящика применима на всех уровнях тестирования (от модульного до приемочного), для которых существует спецификация. Например, при осуществлении системного или интеграционного тестирования, требования или функциональная спецификация будут основой для написания тест-кейсов.

Техники тест-дизайна, основанные на использовании черного ящика, включают:

  • классы эквивалентности;
  • анализ граничных значений;
  • таблицы решений;
  • диаграммы изменения состояния;
  • тестирование всех пар.

Преимущества:

  1. тестирование производится с позиции конечного пользователя и может помочь обнаружить неточности и противоречия в спецификации;
  2. тестировщику нет необходимости знать языки программирования и углубляться в особенности реализации программы;
  3. тестирование может производиться специалистами, независимыми от отдела разработки, что помогает избежать предвзятого отношения;
  4. можно начинать писать тест-кейсы, как только готова спецификация.

Недостатки:

  1. тестируется только очень ограниченное количество путей выполнения программы;
  2. без четкой спецификации (а это скорее реальность на многих проектах) достаточно трудно составить эффективные тест-кейсы;
  3. некоторые тесты могут оказаться избыточными, если они уже были проведены разработчиком на уровне модульного тестирования.

Противоположностью техники черного ящика является тестирование методом белого ящика, речь о котором пойдет ниже.

White Box

Summary: Нам известны все детали реализации тестируемой программы.

Тестирование методом белого ящика (также прозрачного, открытого, стеклянного ящика или же основанное на коде или структурное тестирование) – метод тестирования программного обеспечения, который предполагает, что внутренняя структура/устройство/реализация системы известны тестировщику. Мы выбираем входные значения, основываясь на знании кода, который будет их обрабатывать. Точно так же мы знаем, каким должен быть результат этой обработки. Знание всех особенностей тестируемой программы и ее реализации обязательны для этой техники. Тестирование белого ящика – углубление во внутреннее устройство системы за пределы ее внешних интерфейсов.

Согласно ISTQB: тестирование белого ящика – это:

  • тестирование, основанное на анализе внутренней структуры компонента или системы;
  • тест-дизайн, основанный на технике белого ящика – процедура написания или выбора тест-кейсов на основе анализа внутреннего устройства системы или компонента.

Почему «белый ящик»? Тестируемая программа для тестировщика – прозрачный ящик, содержимое которого он прекрасно видит.

Пример:

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

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

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

Преимущества:

  1. тестирование может производиться на ранних этапах: нет необходимости ждать создания пользовательского интерфейса;
  2. можно провести более тщательное тестирование с покрытием большого количества путей выполнения программы.

Недостатки:

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

Сравнение Black Box и White Box

Grey Box

Summary: Нам известны только некоторые особенности реализации тестируемой системы.

Тестирование методом серого ящика – метод тестирования программного обеспечения, который предполагает комбинацию White Box и Black Box подходов. То есть внутреннее устройство программы нам известно лишь частично. Предполагается, например, доступ ко внутренней структуре и алгоритмам работы ПО для написания максимально эффективных тест-кейсов, но само тестирование проводится с помощью техники черного ящика, то есть с позиции пользователя.

Эту технику тестирования также называют методом полупрозрачного ящика: что-то мы видим, а что-то – нет.

Пример:

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

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

Тестирование черного и белого ящика | Жизнь — это движение! А тестирование

Черный ящик (black box testing)

Тестирование черного ящика — это когда мы не знаем, как система устроена внутри. У нас нет доступа к коду или мы не умеем его читать. Поэтому ориентируемся только на внешнее поведение или ТЗ.

Это начинающий автомобилист. Заглянуть под капот? Ой, там слишком страшно, будем верить приборам и точка.

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

Если я сейчас открою любой сайт:

И начну его тестировать: «А что, если платьюшко именно красное поискать? А красное с белым? А книгу по автору? А если спецсимволы вбить?», и так далее → это как раз тестирование черного ящика. Доступа к коду у меня нет, я просто проверяю, как программа работает.

У меня либо есть ТЗ (как в случае Users, вот тех задание), либо его нету, как в случае интернет-магазина или форума. Составляю тесты, выполняю через интерфейс, типичный black box.

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

Белый ящик (white box testing)

Тестирование белого ящика — это когда у нас есть доступ к коду, и мы его тестируем. Читаем сам код (статическое тестирование), запускаем в дебаге, пишем автотесты…

Если сравнивать с автомобилистом, то тут уже не новичок, а прошаренный. Сломалось что-то? Нафиг приборы, сразу лезем под капот, где все устройство чуть ли не наизусть уже знаем. Роемся там, ищем причину…

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

Как пример открытого проекта — Folks, его можно скачать, запустить, и даже написать свои автотесты, прогон которых как раз и будет тестированием самого кода, белого ящика. User interface у folks нет и не будет, так что тестирование черного ящика там недоступно.

Плюсы подхода — можно писать меньше тестов. Мы ведь знаем, что тут и тут будет работать одинаково, видим по коду. Но иногда настолько углубляемся в код, что читаем именно его, а не ТЗ, и можем пропустить какие-то баги (см плюсы черного ящика)

Серый ящик (gray box testing)

Тестирование серого ящика — это совмещение. Мы смотрим в код и понимаем, как он устроен. А потом открываем само приложение и проверяем, как этот код отображается уже в нем, но ориентируемся уже больше на ТЗ.

На примере автомобилиста это самый распространенный сценарий. Чтобы получить права, мы должны пройти специальный курс, на котором рассказывается, как устроена машина внутри → это знание кода, white box. Но потом мы начинаем кататься на своей машине и в основном ориентируемся на приборы → user interface, black box. При этом мы трактуем показания приборов на основе знаний кода.

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

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

Главное, чтобы доступ к коду дали, хотя бы частичный ツ

Хотя есть и другая версия — знание высокоуровневой структуры приложения: модулей, баз, например, но без доступа к коду. Или знание алгоритма, но опять же без доступа к собственно коду. Например, по псевдокоду.

Но смысл один: мы что-то из кода знаем, а что-то нет.

См также:
White/Black/Grey Box-тестирование — тоже хорошая статья на эту тему!



PS: Статья написана в помощь студентам моей Школы для начинающих тестировщиков.


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

Что такое тестирование WHITE Box? Методы, примеры, типы и инструменты

  • На главную
  • Тестирование

      • Назад
      • Гибкое тестирование
      • BugZilla
      • Cucumber
      • Тестирование базы данных
      • Jmeter
      • Jmeter Testing
      • JUnit
      • LoadRunner
      • Ручное тестирование
      • Мобильное тестирование
      • Mantis
      • Почтальон
      • QTP
      • Назад
      • Центр качества (ALM)
      • 000
      • Центр качества (ALM)
      • 000 Управление тестированием

      • TestLink
  • SAP

      • Назад
      • ABAP
      • 9000 3 APO

      • Начинающий
      • Basis
      • BODS
      • BI
      • BPC
      • CO
      • Назад
      • CRM
      • Crystal Reports
      • MMO
      • HAN

      • Назад
      • PI / PO
      • PP
      • SD
      • SAPUI5
      • Безопасность
      • Менеджер решений
      • Successfactors
      • SAP Tutorials
  • Web
  • Web
  • AngularJS
  • ASP.Net
  • C
  • C #
  • C ++
  • CodeIgniter
  • СУБД
  • JavaScript
  • Назад
  • Java
  • JSP
  • Kotlin
  • Linux
  • Linux
  • Kotlin
  • Linux
  • js

  • Perl
  • Назад
  • PHP
  • PL / SQL
  • PostgreSQL
  • Python
  • ReactJS
  • Ruby & Rails
  • Scala
  • SQL
  • 000

  • SQL
  • 000

    0003 SQL

    000

    0003 SQL

    000

  • UML
  • VB.Net
  • VBScript
  • Веб-службы
  • WPF
  • Обязательно учите!

      • Назад
      • Бухгалтерский учет
      • Алгоритмы
      • Android
      • Блокчейн
      • Business Analyst
      • Создание веб-сайта
      • CCNA
      • Облачные вычисления
      • 0003 COBOL
      • 000 Compiler
          9000 Встроенный

        • 000 9000 Compiler
        • Ethical Hacking
        • Учебники по Excel
        • Программирование на Go
        • IoT
        • ITIL
        • Jenkins
        • MIS
        • Сети
        • Операционная система
        • 0003
        • Назад
        • Управление проектами Обзоры
        • Salesforce
        • SEO
        • Разработка программного обеспечения
        • VB A
    • Big Data

        • Назад
        • AWS
        • BigData
        • Cassandra
        • Cognos
        • Хранилище данных
        • 0003

        • HBOps
        • 0003

        • HBOps
        • 0003

        • MicroStrategy

    .

    Тестирование белого ящика, примеры, методы, плюсы и минусы

    White Box Testing — это стратегия тестирования программного обеспечения, которая проверяет приложение, в то время как его внутренняя структура, дизайн и детали реализации доступны для тестировщиков. У него много названий, таких как тестирование прозрачного ящика или тестирование открытого ящика, или тестирование прозрачного ящика, или тестирование прозрачного ящика, или тестирование на основе кода, или структурное тестирование.

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

    Тестирование белого ящика для начинающих

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

    Белый ящик Тестирование согласно ISTQB

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

    Белый ящик Тестирование:

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

    Белый ящик Процесс разработки теста:

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

    Белый ящик Сценарий тестирования:

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

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

    Тестирование белого ящика Применимо к:

    Этот метод затрагивает следующие области ручного тестирования:

    1.Модульное тестирование:

    Здесь наименьшая единица кода определяет возможные пути для проверки.

    2. Интеграционное тестирование:

    В этом потоке тестер выполняет проверку между двумя или более модулями приложения.

    3. Тестирование системы:

    Эта фаза — фаза стабильности, где QA находит и исследует пути между различными подсистемами.

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

    Белый ящик Методы тестирования:

    Следующие методы помогают как в написании тестовых случаев, так и в выполнении.

    1. Обнаружение утечки памяти:

    Здесь тестировщики сосредотачиваются на поиске проблем, таких как переполнение стека, переполнение буфера, утечка памяти и т. Д. Такие инструменты, как Valgrind, детектор утечки памяти C ++, привыкли поддерживать этот уровень.

    2. Охват кода:

    Покрытие кода также измеряется, чтобы убедиться, что процент кода, покрываемый тестами белого ящика.Этот процесс может помочь тестировщикам писать кейсы для областей, которые остаются нетронутыми. Здесь такие инструменты, как валидатор покрытия кода C ++, GCOV, облегчают этот уровень.

    У этой техники есть три разных уровня.

    i) Покрытие заявления:

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

    Возвращает общее количество исполняемых строк приложения, проверенных выполненными тестами.

    ii) Покрытие филиала:

    Ветвь указывает инструкции, которые включают использование предложения IF в коде.

    Предложение IF имеет два возможных ответвления: Успех и Неудача.

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

    ii) Покрытие пути:

    Покрытие пути фокусируется на определении тестов, охватывающих все возможные пути в приложении.

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

    Белый ящик Преимущества тестирования:

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

    Белый ящик Недостатки тестирования:

    1.Дизайн теста белого ящика сложен, требует соответствующих навыков программирования и ресурсов, обладающих глубокими знаниями в области дизайна приложения.
    2. Управление тестовым кодом и скриптами — это дополнительные задачи, требующие дополнительных усилий.
    3. Этот тип тестирования тесно связан с источником тестируемого приложения. Следовательно, частые изменения в коде требуют повторного выполнения, а иногда даже приводят к новым путям для тестирования.

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

    .

    Полное руководство с методами, примерами и инструментами

    Что такое тестирование методом «белого ящика»?

    Если следовать определению, «тестирование белого ящика» (также известное как тестирование прозрачного, стеклянного ящика или структурное тестирование) — это метод тестирования, который оценивает код и внутреннюю структуру программы.

    Тестирование «белого ящика» включает изучение структуры кода. Если вы знаете внутреннюю структуру продукта, можно провести тесты, чтобы убедиться, что внутренние операции выполняются в соответствии со спецификацией.И все внутренние компоненты отработаны должным образом.

    Мой опыт

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

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

    Но как говорится «Всегда есть темная сторона» .

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

    Покрытие

    Тестирование белого ящика — это покрытие спецификации в коде:

    1. Покрытие кода

    2. Покрытие сегмента: Убедитесь, что каждый оператор кода выполняется один раз.

    3. Покрытие ветви или тестирование узла: Покрытие каждой ветви кода из всех возможных было.

    4. Покрытие сложных условий: Для нескольких условий проверьте каждое условие с несколькими путями и комбинацией разных путей для достижения этого условия.

    5. Тестирование базового пути: Каждый независимый путь в коде берется для тестирования.

    6. Тестирование потока данных (DFT): В этом подходе вы отслеживаете конкретные переменные посредством каждого возможного вычисления, таким образом определяя набор промежуточных путей через код. DFT имеет тенденцию отражать зависимости, но в основном это происходит через последовательности данных манипуляции.Короче говоря, каждая переменная данных отслеживается, и ее использование проверяется. Этот подход имеет тенденцию обнаруживать ошибки, такие как переменные, которые используются, но не инициализируются, или объявлены, но не используются, и так далее.

    7. Тестирование пути: Тестирование пути — это определение и покрытие всех возможных путей прохождения кода. Это трудоемкая задача.

    8. Тестирование циклов: Эти стратегии относятся к тестированию одиночных циклов, составных циклов и вложенных циклов. С помощью этого подхода проверяются независимые и зависимые циклы и значения кода.

    Почему мы проводим WBT?

    Чтобы убедиться:

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

    Выявить следующие типы ошибок:

    • Логическая ошибка имеет тенденцию вкрадываться в нашу работу, когда мы проектируем и реализуем функции, условия или элементы управления, которые не входят в программу. ход программы и фактическая реализация
    • Типографические ошибки и проверка синтаксиса
    Требуются ли для этого тестирования подробные навыки программирования?

    Нам нужно написать тестовые примеры, обеспечивающие полное покрытие логики программы.

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

    Ограничения

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

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

    Разница между тестированием «белого ящика» и «черного ящика»

    Проще говоря:

    При тестировании «черного ящика» мы тестируем программное обеспечение с точки зрения пользователя, а в «белом ящике» мы видим и тестируем реальную код.

    При тестировании черного ящика мы выполняем тестирование, не видя внутренний системный код, но в WBT мы видим и тестируем внутренний код.

    Методика тестирования «белого ящика» используется как разработчиками, так и тестировщиками. Это помогает им понять, какая строка кода на самом деле выполняется, а какая нет.Это может указывать на то, что здесь отсутствует логика или опечатка, что в конечном итоге может привести к некоторым негативным последствиям.

    Рекомендуемое чтение => Полное руководство по тестированию черного ящика

    Шаги по выполнению WBT

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

    Шаг № 2 — Создайте тесты и выполните их.

    Когда мы обсуждаем концепцию тестирования, «покрытие» считается наиболее важным фактором. Здесь я объясню, как получить максимальное покрытие в контексте тестирования белого ящика.

    Также прочтите => Диаграмма причин и следствий — метод написания динамических тестовых примеров для максимального охвата

    Типы и методы тестирования белого ящика

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

    См. Изображение ниже для справки.

    Сегодня мы сосредоточимся в основном на типах тестирования исполнения «Техники модульного тестирования белого ящика».

    3 основных метода тестирования «белого ящика»:

    1. Покрытие заявлений
    2. Покрытие ответвлений
    3. Покрытие путей

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

    Давайте разберемся с этими методами одну за другой на простом примере.

    # 1) Покрытие операторов:

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

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

    # 2) Охват ветвей:

    «Ветвь» в языке программирования подобна «операторам IF». Оператор IF имеет две ветви: T rue и False .

    Итак, в зоне покрытия ветвей (также называемой покрытием решений) мы проверяем, выполняется ли каждая ветка хотя бы один раз.

    В случае «оператора IF» будут два условия тестирования:

    • Одно для проверки истинного перехода и
    • Другое для проверки ложного перехода.

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

    # 3) Покрытие пути

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

    Давайте рассмотрим простой пример, чтобы понять все эти методы тестирования белого ящика.

    Также отметьте => Различные типы тестирования

    Пример тестирования белого ящика

    Рассмотрим простой псевдокод ниже:

     INPUT A & B
    С = А + В
    ЕСЛИ C> 100
    ПЕЧАТЬ «СДЕЛАНО» 

    Для покрытия Statement — нам понадобится только один тестовый пример, чтобы проверить все строки кода.

    Это означает:

    Если я считаю, что TestCase_01 (A = 40 и B = 70), , тогда все строки кода будут выполнены.

    Теперь возникает вопрос:

    1. Этого достаточно?
    2. Что, если я считаю свой тестовый случай A = 33 и B = 45?

    Поскольку покрытие Statement будет охватывать только истинную сторону псевдокода, только одного тестового примера НЕ будет достаточно для его проверки. Как тестировщик, мы должны учитывать и отрицательные случаи.

    Следовательно, для максимального покрытия нам необходимо рассмотреть « Branch Coverage » , который будет оценивать условия «FALSE».

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

    Итак, теперь псевдокод становится:

     INPUT A и B
    
    С = А + В
    ЕСЛИ C> 100
    ПЕЧАТЬ «СДЕЛАНО»
    ELSE
    
    ПЕЧАТЬ «ЕГО В ОЖИДАНИИ» 

    Поскольку покрытия оператора недостаточно для тестирования всего псевдокода, нам потребуется покрытие Branch для обеспечения максимального покрытия .

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

    TestCase_01 : A = 33, B = 45

    TestCase_02 : A = 25, B = 30

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

    Вот выводы, которые сделаны на данный момент:

    • Покрытие ветвей обеспечивает большее покрытие, чем покрытие Statement.
    • Покрытие ветвей более мощное, чем покрытие Statement.
    • 100% покрытие ветвей само по себе означает 100% покрытие операторов.
    • Но 100% покрытие выписки не гарантирует 100% покрытие филиала.

    Теперь перейдем к Покрытие пути:

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

    Рассмотрим этот псевдокод:

     INPUT A и B
    С = А + В
    ЕСЛИ C> 100
    ПЕЧАТЬ «СДЕЛАНО»
    
    КОНЕЦ ЕСЛИ
    ЕСЛИ A> 50
    ПЕЧАТЬ «ЕГО В РАССМОТРЕНИИ»
    END IF 

    Теперь, чтобы обеспечить максимальное покрытие, нам потребуется 4 тестовых примера.

    Как? Проще говоря — есть 2 утверждения решения, поэтому для каждого утверждения решения нам понадобится две ветви для тестирования. Один для истинного, а другой — для ложного. Таким образом, для двух утверждений решения нам потребуется 2 тестовых примера для проверки истинной стороны и 2 тестовых примера для проверки ложной стороны, что составляет в общей сложности 4 тестовых примера.

    Чтобы упростить это, давайте рассмотрим ниже блок-схему псевдокода, который у нас есть:

    Чтобы иметь полное покрытие, нам понадобятся следующие тестовые примеры:

    TestCase_01: A = 50, B = 60

    TestCase_02 : A = 55, B = 40

    TestCase_03: A = 40, B = 65

    TestCase_04: A = 30, B = 30

    Таким образом, пройденный путь будет :

    Красная линия — TestCase_01 = (A = 50, B = 60)

    Синяя линия = TestCase_02 = (A = 55, B = 40)

    Оранжевая линия = TestCase_03 = (A = 40, B = 65)

    Зеленая линия = TestCase_04 = (A = 30, B = 30)

    ******************
    = >> Свяжитесь с нами , чтобы предложить свое объявление здесь
    *****************

    Инструменты для тестирования белого ящика

    Ниже приведен список основных инструментов тестирования белого ящика.

    # 1) Veracode

    Инструменты тестирования белого ящика Veracode помогут вам быстро и легко выявлять и устранять недостатки программного обеспечения при меньших затратах. Он поддерживает несколько языков приложений, таких как .NET, C ++, JAVA и т. Д., А также позволяет тестировать безопасность настольных, веб-и мобильных приложений. Тем не менее, у Veracode есть несколько других преимуществ. Для получения подробной информации об инструментах тестирования Veracode White box, пожалуйста, перейдите по ссылке ниже.

    Ссылка на веб-сайт: Veracode

    # 2) EclEmma

    Первоначально EclEmma была разработана для тестовых прогонов и анализа в рабочей среде Eclipse. Он считается бесплатным инструментом для покрытия кода Java и также имеет несколько функций. Чтобы установить EclEmma или узнать больше о ней, перейдите по ссылке ниже.

    Ссылка на веб-сайт: EclEmma

    # 3) RCUNIT

    Фреймворк, который используется для тестирования программ C, известен как RCUNIT.RCUNIT может использоваться соответствующим образом в соответствии с условиями лицензии MIT. Его можно использовать бесплатно, и для того, чтобы установить или узнать о нем больше, перейдите по ссылке ниже.

    Ссылка на веб-сайт: RCUNIT

    # 4) cfix

    cfix — одна из сред модульного тестирования для C / C ++, единственная цель которой — сделать разработку наборов тестов максимально простой и легкой. Между тем, cfix обычно специализируется на режиме ядра NT и Win32. Чтобы установить и узнать больше о cfix, перейдите по ссылке ниже

    Ссылка на веб-сайт: cfix

    # 5) Googletest

    Googletest — это среда тестирования C ++ от Google.Обнаружение тестов, тесты на смерть, тесты с параметризацией значений, фатальные и нефатальные сбои, создание отчета о тестировании XML и т. Д. — это несколько функций GoogleTest, но есть и несколько других функций. Linux, Windows, Symbian, Mac OS X — это несколько платформ, на которых использовался GoogleTest. Чтобы скачать, перейдите по ссылке ниже.

    Ссылка для скачивания: Googletest

    # 6) EMMA

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

    Ссылка для скачивания: EMMA

    # 7) NUnit

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

    Ссылка для скачивания: NUnit

    # 8) CppUnit

    CppUnit — это фреймворк для модульного тестирования, написанный на C ++ и считается портом JUnit. Тестовый вывод для CppUnit может быть в формате XML или в текстовом формате. Он создает модульные тесты со своим собственным классом и запускает тесты в наборах тестов. Он под лицензией LGPL. Чтобы загрузить и узнать больше о CppUnit, перейдите по ссылке ниже.

    Ссылка для загрузки: CppUnit

    # 9) JUnit

    JUnit — это тихая простая среда модульного тестирования, которая поддерживает автоматизацию тестирования на языке программирования Java. Он в основном поддерживает разработку через тестирование, а также предоставляет отчет о покрытии тестами. Он находится под лицензией Eclipse Public License. Чтобы бесплатно загрузить и узнать больше о JUnit, перейдите по ссылке ниже.

    Ссылка для скачивания: JUnit

    # 10) JsUnit

    JsUnit считается портом JUnit для javascript.И это среда модульного тестирования с открытым исходным кодом для поддержки клиентского Javascript. Он находится под лицензией GNU Public License 2.0, GNU Lesser Public License 2.1 и Mozilla Public License 1.1. Чтобы загрузить и узнать больше о JsUnit, перейдите по ссылке ниже.

    Ссылка для скачивания: JsUnit

    Также проверьте все инструменты, которые мы перечислили в разделе Статический анализ кода здесь .

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

    Заключение

    Полагаться только на тестирование черного ящика недостаточно для максимального охвата тестированием. Нам необходимо сочетание методов тестирования «черного ящика» и «белого ящика», чтобы охватить максимальное количество дефектов.

    Если все сделано правильно, тестирование «белого ящика», безусловно, повлияет на качество программного обеспечения. Участие в этом тестировании также полезно для тестировщиков, поскольку оно может дать наиболее «объективное» мнение о коде. 🙂

    Сообщите нам, если у вас есть какие-либо вопросы о методах, которые мы обсуждали в этой статье.

    .

    White Box Testing — Основы ТЕСТИРОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

    WHITE BOX TESTING (также известный как Clear Box Testing, Open Box Testing, Glass Box Testing, Transparent Box Testing, Code-Based Testing или Structural Testing) — это метод тестирования программного обеспечения, в котором внутренняя структура / дизайн / реализация тестируемого элемента известны тестировщику.

    Определение ISTQB

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

    Разработка

    Во время тестирования методом «белого ящика» тестер выбирает входные данные для проверки путей прохождения кода и определяет соответствующие выходы. Важны ноу-хау в области программирования и знания о реализации. Тестирование методом белого ящика — это тестирование, выходящее за рамки пользовательского интерфейса и в мельчайшие детали системы.Этот метод назван так потому, что программа в глазах тестировщика похожа на белый / прозрачный ящик; внутри которого ясно видно.

    Пример

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

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

    Уровни

    Метод

    White Box Testing применим к следующим уровням тестирования программного обеспечения:

    Однако в основном это применяется к модульному тестированию.

    Преимущества

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

    Недостатки

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

    Тестирование белого ящика отличается от тестирования черного ящика. Прочтите «Различия между тестированием черного ящика» и «Белым ящиком».

    (Значок, используемый на изображении, был сделан доктором медицины Бадша Меа с сайта www.freeicons.io )

    .

    По мере того, как индустрия программного обеспечения переходит от водопадного подхода к гибкой разработке программного обеспечения, вы ДОЛЖНЫ также узнать о AGILE TESTING .

    .

    Последнее обновление 17 сентября 2020 г., STF

    .

  • Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *