DATA FLOW: СТАТИЧЕСКИЙ АНАЛИЗ ПОТОКА ДАННЫХ

Всем привет, сегодняшняя тема об аналитике данных в рамках тестирования!

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

Так вот эти методы почти всегда применяются к группам данных в рамках одной большой детерминированной (те принимающей на вход и отдающей на выход определённые данные) программы.

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

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

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

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

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

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

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

Ошибки потока данных - это последовательности действий над переменной в программе, которые предположительно являются ошибочными.
В теории любая переменная в программе может быть:
- D (определённой) - присвоено значение.
- R (указанной) - имеет используемое значение.
- U (undefined) - её значение (если есть) уничтожается (напр. когда переменная впервые объявляется, предполагается, что она определена, и когда переменная выходит за пределы области видимости она становится неопределенной).

В терминах этих состояний можно определить три типа ошибок потока данных:
1. Можно ссылаться на переменную, значение которой не определено (ошибка UR).
2. Определенная переменная может быть переопределена без ссылки на переменную после первого определения (ошибка DD).
3. Определенная переменная может стать неопределенной без ссылки на переменную после определения (ошибка DU).

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

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

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

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

Анализ мутаций
Когда все скрипты тестирования готовы и выполняются в тестах, можно встретить очень частую проблему - это недостаток уверенности в том, что скрипты обнаружат все ошибки. Анализ мутаций помогает выявить упущения.
Анализ мутаций проверяет тесты и их данные, запуская их во множестве копий программы, каждая из которых содержит отдельное, намеренно внесённое изменение.Если тесты регистрируют изменения, они считаются хорошими. Типичные мутации заменяют все + и -. В основе этого подхода лежат две теории:
1. Большое количество ошибок вызвано простейшими опечатками программиста, такими как использование AND вместо OR, + вместо - и SQRT (X) вместо X ** 2, или наоборот.
Это называется теорией грамотного программиста.
2. Вторая теория называется теорией эффекта связи, которая значит что если тестовый пример может найти простую ошибку, то он найдёт и сложную.
Мутационное тестирование создает одну или несколько копий некоторого исходного кода и изменяет его так, чтобы один или несколько скриптов изменяли свой результат выполнения.
При мутационном тестировании было выявлено несколько багов:
- Виды внесённых изменений могут не отражать ошибки в программе напр, множественные или временные ошибки), которые тесты могут не обнаружить. Также может потребоваться большое количество тестов. Однако их можно просто создать, используя несколько команд операционной системы и генератор случайных чисел.
Создание всех возможных мутантов очень затратно даже с помощью такого инструмента, как Mothra, С помощью него проводится тестирование слабой мутации, при котором состояние после мутации сравнивается с неизмененным состоянием. На практике из 22 операторов, используемых в Mothra, только 5 являются важными:

- ABS: заставляет каждое арифметическое выражение принимать 0, положительное и отрицательное значения.
- AOR: заменяет каждый арифметический оператор всеми синтаксически допустимыми операторами по очереди.
- LCR: заменяет каждый логический оператор (И и ИЛИ) на несколько типов логических соединителей.
- ROR: заменяет реляционные операторы другими реляционными операторами.
- UOI: вставляет унарные операторы перед .
- На практике, то есть через набор тестов.
Мутированный код также может исправить ошибку в исходном коде и таким образом скрыть ее.
Если код просто несовершенен, но работает, то никакое количество тестов на мутации не выявит этого.
- Инструментирование измененного кода для выявления ошибок, которые должны обнаружить, сгенерировать большие объемы кода, и мутант-тест, помещенный в начале кода, может сам заблокировать выполнение более позднего теста.
- В тестируемой системе может использоваться самописанный язык программирования.
Если тесты не обнаруживают внесенных изменений, тогда они дорабатываются. Мутационные тесты полезны для выявления незначительных, но важных ошибок в коде, допускаемые даже опытными разработчиками.

Внедрение ошибок
Цель внедрения ошибок - ответить на вопрос "насколько хорошо это ПО будет работать?"
Результат достигается путем моделирования ошибок программиста, сбоев модулей (таких как неисправные датчики), делая исходный код более "хрупким", чтобы увеличить вероятность появления бага. Выявление ошибки путем ее "распространения" "хрупкости" программного обеспечения также зависит от количества изменений, необходимых для выявления ошибки. 

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

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

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

Наш твитр: @derkodierer

Comments

Popular posts from this blog

THE ANONYMOUS SHIELD

HOW'S ROUTER WORKING? DHCP