\documentclass[a4paper, final]{article}
%\usepackage{literat} % Нормальные шрифты
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
\usepackage{tabularx}
\usepackage[T2A]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[russian]{babel}
\usepackage{amsmath}
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
\usepackage{ragged2e} %для растягивания по ширине
\usepackage{setspace} %для межстрочно   го интервала
\usepackage{moreverb} %для работы с листингами
\usepackage{indentfirst} % для абзацного отступа
\usepackage{moreverb} %для печати в листинге исходного кода программ
\usepackage{pdfpages} %для вставки других pdf файлов
\usepackage{tikz}
\usepackage{graphicx}
\usepackage{afterpage}
\usepackage{longtable}
\usepackage{float}



% \usepackage[paper=A4,DIV=12]{typearea}
\usepackage{pdflscape}
% \usepackage{lscape}

\usepackage{array}
\usepackage{multirow}

\renewcommand\verbatimtabsize{4\relax}
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
\usepackage{listings} %листинги
\usepackage{xcolor} % цвета
\usepackage{hyperref}% для гиперссылок
\usepackage{enumitem} %для перечислений

\newcommand{\specialcell}[2][l]{\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}}


\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях

\hypersetup{colorlinks,
    allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)

% подгружаемые языки — подробнее в документации listings (это всё для листингов)
\lstloadlanguages{ SQL}
% включаем кириллицу и добавляем кое−какие опции
\lstset{tabsize=2,
    breaklines,
    basicstyle=\footnotesize,
    columns=fullflexible,
    flexiblecolumns,
    numbers=left,
    numberstyle={\footnotesize},
    keywordstyle=\color{blue},
    inputencoding=cp1251,
    extendedchars=true
}
\lstdefinelanguage{MyC}{
    language=SQL,
%    ndkeywordstyle=\color{darkgray}\bfseries,
%    identifierstyle=\color{black},
%    morecomment=[n]{/**}{*/},
%    commentstyle=\color{blue}\ttfamily,
%    stringstyle=\color{red}\ttfamily,
%    morestring=[b]",
%    showstringspaces=false,
%    morecomment=[l][\color{gray}]{//},
    keepspaces=true,
    escapechar=\%,
    texcl=true
}

\textheight=24cm % высота текста
\textwidth=16cm % ширина текста
\oddsidemargin=0pt % отступ от левого края
\topmargin=-1.5cm % отступ от верхнего края
\parindent=24pt % абзацный отступ
\parskip=5pt % интервал между абзацами
\tolerance=2000 % терпимость к "жидким" строкам
\flushbottom % выравнивание высоты страниц


% Настройка листингов
\lstset{
    language=python,
    extendedchars=\true,
    inputencoding=utf8,
    keepspaces=true,
    % captionpos=b, % подписи листингов снизу
}

\begin{document} % начало документа
    


    % НАЧАЛО ТИТУЛЬНОГО ЛИСТА
    \begin{center}
        \hfill \break
        \hfill \break
        \normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
            федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
        \normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt] 
        \normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt] 
        \normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
        
        \hfill \break
        \hfill \break
        \hfill \break
        \hfill \break
        \large{Лабораторная работа №2}\\
        \large{<<Тестирование ПО методом белого и чёрного ящика>>}\\
        \large{по дисциплине}\\
        \large{<<Методы тестирования программного обеспечения>>}\\
        \hfill \break
        
        % \hfill \break
        \hfill \break
    \end{center}
    
    \small{ 
        \begin{tabular}{lrrl}
            \!\!\!Студент, & \hspace{2cm} & & \\
            \!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
            \!\!\!Преподаватель & \hspace{2cm} &  \underline{\hspace{3cm}} &  Курочкин М. А. \\\\
            &&\hspace{4cm}
        \end{tabular}
        \begin{flushright}
            <<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2025г.
        \end{flushright}
    }
    
    \hfill \break
    % \hfill \break
    \begin{center} \small{Санкт-Петербург, 2025} \end{center}
    \thispagestyle{empty} % выключаем отображение номера для этой страницы
    
    % КОНЕЦ ТИТУЛЬНОГО ЛИСТА
    \newpage
    
    \tableofcontents


    \newpage
    \section*{Введение}
    \addcontentsline{toc}{section}{Введение}
    Одним из ключевых этапов в современной разработке программного обеспечения является тестирование. Существует несколько видов тестирования: модульное, интеграционное, функциональное, системное и приемочное. В данной работе будет рассмотрено модульное тестирование.

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

    Существует два основных подхода к unit-тестированию: методы <<чёрного>> и <<белого ящика>>.

    В данной работе будут рассмотрены оба метода. Также данные приёмы будут применены для тестирования двух программ:

    \begin{itemize}
        \item вычисление факториала числа;
        \item возведение числа в степень.
    \end{itemize}

    Каждая из программ будет протестирована обоими методами с целью сравнения подходов.


    \newpage
    \section{Постановка задачи}
    Цель работы: провести тестирование двух программ методами <<черного ящика>> и <<белого ящика>>. Для достижения цели, были выделены следующие задачи:

    \begin{itemize}
        \item Изучить методы модульного тестирования, в частности методы <<белого ящика>> и <<черного ящика>>.
        \item Разработать тесты для двух программ, и провести их тестирование используя оба метода на каждой программе.
        \item Проанализировать результаты тестирования.
    \end{itemize}


    \newpage
    \section {Описание методов тестирования}
    \subsection{Метод черного ящика}
    Метод черного ящика или тестирование управляемое данными, тестирование управляемое входом и выходом -- это метод тестирования, в котором программа рассматривается как <<черный ящик>>, внутреннее
    поведение и структура которого не имеют никакого значения. Вместо этого все внимание фокусируется на выяснении обстоятельств, при которых поведение программы не соответствует спецификации.

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

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

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

    \subsubsection{Эквивалентное разбиение}
    Класс эквивалентности -- конечный набор входных данных, позволяющий допускать, что тестирования представительного значения данного класса эквивалентно тестированию любого другого значения принадлежащего тому же классу.

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

    \begin{itemize}
        \item уменьшение более чем на единицу числа других тестов, которые
        должны быть разработаны для достижения поставленной цели
        <<обеспечить приемлемое тестирование>>;
        \item покрытие значительной части других возможных тестов, т.е. предоставление некой информации относительно наличия или отсутствия
        ошибок в ситуациях, не охватываемых данным конкретным набором входных значений.
    \end{itemize}

    \subsubsection*{Определение классов эквивалентности}
    Определение классов эквивалентности сводится к последовательному рассмотрению каждого из входных условий (обычно это предложение
    или фраза, приведенные в спецификации) и разбиению его на две или
    несколько групп.

    Определяется два типа классов:
    \begin{itemize}
        \item допустимые классы эквивалентности -- допустимые входные данные программы;
        \item недопустимые классы эквивалентности -- все остальные возможные состояния условий (т.е. недопустимые входные значения).
    \end{itemize}

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

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

    \subsubsection*{Разработка тестов}

    Определение тестов по построенным классам эквивалентности состоит из трех этапов:
    \begin{enumerate}
        \item назначить каждому классу эквивалентности уникальный номер;
        \item записать новые тесты, охватывающие как можно большее количество оставшихся неохваченными допустимых классов эквивалентности, пока не будут покрыты все допустимые классы;
        \item записать новые тесты, каждый из которых охватывает один и только один из оставшихся неохваченными недопустимых классов эквивалентности, пока не будут покрыты все недопустимые классы.
    \end{enumerate}

    \subsubsection{Анализ граничных значений}
    Граничные условия -- это ситуации, возникающие в области граничных значений входных эквивалентности. Анализ граничных значений отличается от методики разбиения на классы эквивалентности в следующем отношении:
    вместо того чтобы выбирать любой элемент класса эквивалентности в качестве представителя всего класса, анализ граничных значений требует выбирать такой элемент или элементы, которые обеспечивают тестирование каждой границы класса.

    \subsubsection{Причинно-следственные диаграммы}
    Метод причинно-следственных диаграмм или метод диаграмм Исикавы -- метод, позволяющий выбирать высокорезультативные тесты.
    Его дополнительным преимуществом является то, что он позволяет обнаруживать неполноту и неоднозначность исходных спецификаций.
    
    Метод позволяет решить проблему того, что метод анализа граничных значений и разбиения данных на классы эквивалентности не исследует комбинации входных условий.

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

    Для построения тестов используется процесс, включающий несколько этапов:
    \begin{enumerate}
        \item Спецификация разбивается на части, с которыми легче работать.
        \item В спецификации определяются причины и следствия.
        
        Причина -- это отдельное входное условие или класс эквивалентности входных условий.
        Следствие -- это выходное условие или преобразование системы
        Причины и следствия определяются путем последовательного (слово за словом) чтения спецификации и подчеркивания тех слов или
        фраз, которые описывают причины и следствия. Каждой причине и каждому следствию присваивается уникальный номер.
        \item Семантическое содержание спецификации анализируется и преобразуется в булев граф, связывающий причины и следствия. Полу-
        ченный граф называется причинно-следственной диаграммой.
        \item Диаграмма снабжается примечаниями, задающими ограничения и
        описывающими комбинации причин и (или) следствий, реализация
        которых невозможна из-за синтаксических или внешних ограничений. Нотация отображений ограничений представлена на Рис.~\ref{fig:img1}.
        \item Путем методичного прослеживания состояний условий диаграмма преобразуется в таблицу решений с ограниченными входами
        (limited-entry decision table). Каждый столбец таблицы решений соответствует тесту.
        \item Столбцы таблицы решений преобразуются в тесты.
    \end{enumerate} 

    Базовая нотация причинно-следственных диаграмм представлена на
    Рис.~\ref{fig:img1}. Каждый узел диаграммы может находиться в двух состояниях: 0
    или 1, где 0 представляет состояние <<отсутствует>>, а 1 -- <<присутствует>>.
    \begin{itemize}
        \item Функция тождество устанавливает, что если а равно 1, то и b равно 1; в противном случае b равно 0.
        \item Функция not устанавливает, что если а равно 1, то b равно 0; в
        противном случае b равно 1.
        \item Функция or устанавливает, что если а, или b, или с равно 1, то d
        равно 1; в противном случае d равно 0.
        \item Функция and устанавливает, что если и а, и b равны 1, то с равно
        1; в противном случае с равно 0.
    \end{itemize}

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.5\linewidth]{img/img1.png}
       \caption{ Базовая нотация, используемая в причинно-следственных диаграммах.}
       \label{fig:img1}
    \end{figure}

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

    \begin{itemize}
        \item Ограничение требует, чтобы всегда выполнялось условие, в соответствии с которым только или только b может быть равно 1 ( и b
        не могут быть равны 1 одновременно, но обе величины могут быть
        равны 0).
        \item Ограничение I требует, чтобы по крайней мере одна из величин, a,
        b или , была равна 1 (, b и не могут быть равны 0 одновременно).
        \item Ограничение требует, чтобы одна и только одна из величин, a или
        b,была равна 1.
        \item Ограничение R требует, чтобы a было равно 1, только если b равно 1 (т.е. не может быть равно 1, если b равно 0). На Рис.~\ref{fig:img2}
        представлены символы ограничений.
    \end{itemize}

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.6\linewidth]{img/img2.png}
       \caption{Базовая нотация ограничений, используемая в причинно-следственных диаграммах.}
       \label{fig:img2}
    \end{figure}

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

     
    \subsection{Метод белого ящика}
    Метод белого ящика -- метод тестирования основанный на анализе внутренней структуры кода. Для данного тестирования используется спецификация программы, описывающая её поведение и блоксхема, по которой тестировщик может осуществлять тестирование на
    уровне отдельных модулей, функций и логики программы.
    Тестирование методом белого ящика имеет и другое название, отражающее суть данной методологии: тестирование с управляемой логикой      
    программы (logic-driving testing). При использовании данной методологии, тестировщик подбирает тестовые данные путём анализа логики программы с учетом её спецификации.
    Исчерпывающее тестирование методом <<белого ящика>> практически
    невозможно в следствии необходимости перебирать огромное количество
    данных. Поэтому для упрощения тестирования применяются следующие
    эвристические методы:     

    \subsubsection{Покрытие операторов}
    Критерий покрытия операторов/инструкций заключается в построении тестов, в которых каждая инструкция выполнялась как минимум один раз. Является необходимым но недостаточным критерием
    для тестирования программы методом <<белого ящика>>

    \subsubsection{Покрытие решений}
    Критерий покрытие решений (decision coverage) или покрытие
    ветвлений заключается в построении тестов таким образом, чтобы каждое условие в программе хотя бы раз принимало как значение true (истина), так и false (ложь). Иными словами, каждая логическая ветвь каждой инструкции ветвления в программе должна быть выполнена хотя бы  
    один раз.
    Обычно покрытие решений удовлетворяет критерию покрытия операторов/инструкций. Однако это правило не действует по крайней мере
    в трех перечисленных ниже случаях.

    \begin{enumerate}
        \item Программы, не содержащие точек ветвления.
        \item Программы или подпрограммы (методы), имеющие несколько точек входа. В таком случае некоторые инструкции будут выполняться лишь тогда, когда выполнение программы начинается с определенной точки входа.
        \item Инструкции в блоках ON. Выполнение всех ветвей не обязательно
        приведет к выполнению всех блоков ON.
    \end{enumerate}

    \subsubsection{Покрытие решений и условий}
    Согласно этому критерию набор тестов является достаточно полным, если выполняются следующие требования:
    \begin{itemize}
        \item каждое условие в решении принимает каждое возможное значение
        по крайней мере один раз;
        \item каждый возможный исход решения проверяется по крайней мере
        один раз;
        \item каждой точке входа управление передается по крайней мере один
        раз.
    \end{itemize}
    Однако, несмотря на кажущуюся возможность охвата им всех возможных исходов решений для всех условий, это зачастую не обеспечивается   
    из-за маскирования одних условий

    \subsubsection{Комбинаторное покрытие условий}
    Комбинаторное покрытие условий (multiple-condition covering) --
    критерий, требующий создания такого количества тестов, при котором
    каждая возможная комбинация результатов вычисления условий в каждом решении и каждая точка входа проверяются по крайней мере один      
    раз.


    \newpage
    \section{Тестирование программы №1}
    \subsection{Формальное описание программы}
    \textbf{Название:} «Вычисление факториала числа».
    
    \textbf{Дано:} 
    \begin{itemize}
        \item $N$ --- целое положительное число.
    \end{itemize}
    
    
    \textbf{Требуется:} Вычислить факториал числа $N$ и вывести результат на экран.
    
    \textbf{Ограничения:}
    \begin{itemize}
        \item $1 \leq N \leq 65$;
        \item $N$ --- целое.
    \end{itemize}

    \textbf{Спецификация}

    \begin{table}[h!]
        \centering
        %\caption{Спецификация}
        %\label{.}
        \footnotesize
        \begin{tabularx}{\textwidth}{|X|X|X|}
        \hline
        \textbf{Входные данные} & \textbf{Выходные данные} & \textbf{Реакция программы} \\
        \hline
        $N = -5$ & ''Ошибка! Введите положительное целое число:'' & Вывод на экран сообщения: ''Ошибка! Введите положительное целое число:''. Ожидание корректного ввода $N$. \\
        \hline
        $N = 5.7$ & ''Ошибка! Введите целое число, а не дробное:'' & Вывод на экран сообщения: ''Ошибка! Введите целое число, а не дробное:''. Ожидание корректного ввода $N$. \\
        \hline
        $N =$ ''пять'' & ''Ошибка! Введите целое число, а не строку:'' & Вывод на экран сообщения: ''Ошибка! Введите целое число, а не строку:''. Ожидание корректного ввода $N$. \\
        \hline
        $N = 70$  & ''Ошибка! Введите целое положительное число, не более 65:'' & Вывод на экран сообщения: ''Ошибка! Введите целое положительное число, не более 65:''. Ожидание корректного ввода $N$. \\
        \hline
        $N = 5$  & 120 & Вывод на экран значения факториала для заданного числа $N$. Завершение программы. \\
        \hline
        $N = 0$  & 1 & Вывод на экран значения факториала для заданного числа $N$. Завершение программы. \\
        \hline
        $N = 1$  & 1 & Вывод на экран значения факториала для заданного числа $N$. Завершение программы. \\
        \hline
        \end{tabularx}
    \end{table}
    
    \newpage
    \textbf{Блок-схема}

    \begin{figure}[h!]
       \centering
       \includegraphics[width=1\linewidth]{img/programm1/block-schema-1.png}
       \caption{Блок схема программы №1.}
       \label{fig:programm1/block-schema-1}
    \end{figure}

    \newpage
    \subsection{Тестирование методом «белого ящика»}
    Алгоритм составления тестов методом «белого» ящика предполагает обход всех
    возможных путей в теле программы и проверку выполнения каждого оператора не
    менее одного раза. Для этого на блок-схеме программы, которая изображена на Рис.~\ref{fig:programm1/block-schema-1}, все возможные пути обозначены символами латинского алфавита от~A~до~I.

    Условия в ветвлениях программы:
    \begin{enumerate}
        \item $N > 65$;
        \item $N < 0$;
        \item $N$ строка?
        \item $N$ дробное?
        \item $k \neq N$
    \end{enumerate}


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

    Для покрытия всех операторов был составлен набор тестов из 6 тестов (Рис.~\ref{fig:programm1/table-operators}).

    \begin{figure}[h!]
       \centering
       \includegraphics[width=1\linewidth]{img/programm1/table-operators.png}
       \caption{Набор тестов для покрытия операторов программы.}
       \label{fig:programm1/table-operators}
    \end{figure}

    \newpage
    При тестировании покрытия операторов был составлен тест (№3), который программа не проходит. Программа не может пройти тест №3, так как была допущена ошибка при составлении блок-схемы программы. При вводе строки программа завершается при попытке сравнить строку с числом 65, хотя по спецификации должна выводить строку <<Ошибка! Введите целое число, а не строку>>.


    \subsubsection{Покрытие решений}
    В соответствии с этим критерием необходимо составить такой набор тестов, при котором каждое условие в программе примет как истинное, так и ложное значения. Таким образом, к тестам, составленным для метода покрытия операторов, необходимо добавить тесты, которые будут проверять все возможные переходы.

    Тесты, покрывающие все решения программы представлены на Рис.~\ref{fig:programm1/table-operators-2}.

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm1/table-operators.png}
        \caption{Набор тестов для покрытия решений программы.}
        \label{fig:programm1/table-operators-1}
    \end{figure}

    Покрыть истинную ветку условия 3 (путь B->D->E) невозможно из-за экстренного завершения программы при вводе строкового значения N.

    \newpage
    \subsubsection{Покрытие условий}
    В соответствии с этим критерием количество тестов должно быть таким, чтобы
    все возможные результаты каждого условия в решении выполнялись по крайней мере
    один раз.

    Тесты, покрывающие все условия программы представлены на Рис.~\ref{fig:programm1/table-operators-2}.

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm1/table-operators.png}
        \caption{Набор тестов для покрытия решений программы.}
        \label{fig:programm1/table-operators-2}
    \end{figure}
    
    Покрыть истинную ветку условия 3 (путь B->D->E) невозможно из-за экстренного завершения программы при вводе строкового значения N.

    \newpage
    \subsubsection{Покрытие решений и условий}
    Согласно этому критерию набор тестов является достаточно полным, если удовлетворяются следующие требования: каждое условие в решении принимает каждое
    возможное значение по крайней мере один раз, каждый возможный исход решения
    проверяется по крайней мере один раз и каждой точке входа управление передается
    по крайней мере один раз.

    Тесты, написанные ранее, обеспечивают покрытие решений и условий (Рис.~\ref{fig:programm1/table-operators-3}).

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm1/table-operators.png}
        \caption{Набор тестов для покрытия решений программы.}
        \label{fig:programm1/table-operators-3}
    \end{figure}
    
    Покрыть истинную ветку условия 3 (путь B->D->E) невозможно из-за экстренного завершения программы при вводе строкового значения N.

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

    Совокупность всех ранее написанных тестов дает покрытие условий и решений (Рис.~\ref{fig:programm1/table-operators-4}).

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm1/table-operators.png}
        \caption{Набор тестов для покрытия решений программы.}
        \label{fig:programm1/table-operators-4}
    \end{figure}
    
    Покрыть истинную ветку условия 3 (путь B->D->E) невозможно из-за экстренного завершения программы при вводе строкового значения N.

    \subsubsection{Результаты тестирования методом <<белого ящика>>}
    В результате тестирования методом «белого ящика» было составлено 6 тестов,
    из которых были пройдены 5 и не пройден 1. При строковом значении $N$ программа
    должна вывести сообщение ”Ошибка! Введите целое число, а не строку:” и ожидать
    повторного ввода значения $N$, однако она экстренно завершается с кодом -1 на первом блоке ветвления ($N$ > 65) при попытке сравнить строку с числом, что означает
    некорректно составленную программу и спецификацию.

    \newpage
    \subsection{Тестирование методом <<чёрного ящика>>}
    \subsubsection{Разбиение на классы эквивалентности}
    Составлено разбиение на классы эквивалентности исходя из ограничений для
    программы, представленное на Рис.~\ref{fig:programm1/classes}. Тесты для допустимых классов эквивалентности представлены на Рис.~\ref{fig:programm1/classes-test-dop} и тесты для недопустимых классов эквивалентности
    — на Рис.~\ref{fig:programm1/classes-test-nedop}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.7\linewidth]{img/programm1/classes.png}
       \caption{Разбиение на классы эквивалентности.}
       \label{fig:programm1/classes}
    \end{figure}
    
    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.9\linewidth]{img/programm1/classes-test-dop.png}
        \caption{Тесты для допустимых классов эквивалентности.}
        \label{fig:programm1/classes-test-dop}
    \end{figure}

    \begin{figure}[h!]
    \centering
    \includegraphics[width=0.9\linewidth]{img/programm1/classes-test-nedop.png}
    \caption{Тесты для недопустимых классов эквивалентности.}
    \label{fig:programm1/classes-test-nedop}
    \end{figure}
    
    \newpage
    При тестировании недопустимых классов эквивалентности был составлен тест, который программа не проходит. Программа не может пройти тест №3, так как была допущена ошибка при составлении блок-схемы программы. При вводе строки программа завершается при попытке сравнить строку с числом 65, хотя по спецификации должна выводить строку <<Ошибка! Введите целое число, а не строку>>.

    \subsubsection{Анализ граничных условий}
    В программе можно выделить следующие граничные условия:
    \begin{itemize}
        \item $N \geq 0$;
        \item $N \leq 65$.
    \end{itemize}
    
    Для каждой из границ определим тесты, соответствующие:
    \begin{itemize}
        \item граничному целому числу (верхнему/нижнему);
        \item целому числу, выходящему за границу (верхнюю/нижнюю) на единицу;
        \item дробному числу, на 0.001 выходящему за границу (верхнюю/нижнюю).
    \end{itemize}
    
    Составленные тесты представлены на Рис.~\ref{fig:programm1/bounds}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.8\linewidth]{img/programm1/bounds.png}
       \caption{Тесты граничных условий.}
       \label{fig:programm1/bounds}
    \end{figure}
    
    При тестировании граничных условий был составлен тест, который программа не проходит. Программа не может пройти тест №1 (Рис.~\ref{fig:programm1/bounds}), так как была допущена ошибка при составлении блок-схемы программы. При вводе числа 0 программа зависает в бесконечном цикле (из-за условия <<k != N>>), хотя по спецификации должна выводить число 1.

    \subsubsection{Причинно-следственная диаграмма}

    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.6\linewidth]{img/programm1/diagram.png}
        \caption{Причинно следственная диаграмма.}
        \label{fig:programm1/diagram}
     \end{figure}

    \textbf{Причины:}
    \begin{enumerate}
        \item $N$ -- число;
        \item $N$ -- целое;
        \item $N \geq 0$;
        \item $N \leq 65$.
    \end{enumerate}
    
    \textbf{Промежуточные причины:}
    \begin{enumerate}
        \item[1.1] $N$ -- целое и $0 \leq N \leq 65$.
    \end{enumerate}
    
    \textbf{Следствия:}
    \begin{enumerate}
        \item[2.1] Программа выводит сообщение об ошибке ($N$ -- строка) и заново запрашивает число;
        \item[2.2] Программа выводит сообщение об ошибке ($N$ -- дробное) и заново запрашивает число;
        \item[2.3] Программа выводит значение факториала для числа $N$;
        \item[2.4] Программа выводит сообщение об (ошибке $N < 0$) и заново запрашивает число;
        \item[2.5] Программа выводит сообщение об (ошибке $N > 65$) и заново запрашивает число.
    \end{enumerate}

    На Рис.~\ref{fig:programm1/diagram} представлена причинно-следственная диаграмма.

    Таблица решений для диаграммы представлена на Рис.~\ref{fig:programm1/table-decisions}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=1\linewidth]{img/programm1/table-decisions.png}
       \caption{Таблица решений.}
       \label{fig:programm1/table-decisions}
    \end{figure}

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

    \subsubsection{Результаты тестирования методом <<чёрного ящика>>}
    В результате тестирования методом чёрного ящика было составлено 11 тестов, из которых не пройдено 2. Ошибки, из-за которых тесты не были пройдены, связаны с некорректной проверкой входных значений и неверно составленной спецификацией: программа экстренно завершается при вводе вместо числа $N$ строки, а также входит в бесконечный цикл при $N = 0$, что не соответствует поведению, описанному в спецификакции.


    
    \newpage
    \section{Тестирование программы №2}
    \subsection{Формальное описание программы}
    \textbf{Название:} «Алгоритм быстрого возведения в степень».
    
    \textbf{Дано:} 
    \begin{itemize}
        \item $n$ --- целое положительное число.
        \item $k$ --- целое положительное число.
    \end{itemize}
    
    
    \textbf{Требуется:} Возвести число $n$ в степень $k$ и вывести результат на экран.
    
    \textbf{Ограничения:}
    \begin{itemize}
        \item $n$ --- целое.
        \item $k$ --- целое.
        \item $1 \leq n \leq 15$;
        \item $1 \leq k \leq 15$;
    \end{itemize}

    \textbf{Спецификация}

    \begin{table}[h!]
        \centering
        %\caption{Спецификация}
        %\label{.}
        \footnotesize
        \begin{tabularx}{\textwidth}{|X|X|X|}
        \hline
        \textbf{Входные данные} & \textbf{Выходные данные} & \textbf{Реакция программы} \\
        \hline
        $n = -5, k = 10$ & ''Ошибка! Введите числа от 1 до 15.'' & Вывод на экран сообщения: ''Ошибка! Введите числа от 1 до 15.''. Ожидание корректного ввода $n$ и $k$. \\
        \hline
        $n = 5, k = -10$ & ''Ошибка! Введите числа от 1 до 15.'' & Вывод на экран сообщения: ''Ошибка! Введите числа от 1 до 15.''. Ожидание корректного ввода $n$ и $k$. \\
        \hline
        $n = 25, k = 10$  & ''Ошибка! Введите числа от 1 до 15.'' & Вывод на экран сообщения: ''Ошибка! Введите числа от 1 до 15.''. Ожидание корректного ввода $n$ и $k$. \\
        \hline
        $n = 5.7, k = 10$ & ''Ошибка! n должно быть целым числом.'' & Вывод на экран сообщения: ''Ошибка! k должно быть целым числом.''. Ожидание корректного ввода $n$ и $k$. \\
        \hline
        $n =$ ''строка'' $, k = 10$ & ''Ошибка! n должно быть целым числом.'' & Вывод на экран сообщения: ''Ошибка! k должно быть целым числом.''. Ожидание корректного ввода $n$ и $k$. \\
        \hline
        $n = 2, k = 10$  & 1024 & Вывод на экран значения $2^10$. Завершение программы. \\
        \hline
        \end{tabularx}
    \end{table}
    
    \newpage
    \textbf{Блок-схема}

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.75\linewidth]{img/programm2/block-schema.png}
       \caption{Блок схема программы №2.}
       \label{fig:programm2/block-schema}
    \end{figure}

    \newpage
    \subsection{Тестирование методом «белого ящика»}
    Алгоритм составления тестов методом «белого» ящика предполагает обход всех
    возможных путей в теле программы и проверку выполнения каждого оператора не
    менее одного раза. Для этого на блок-схеме программы, которая изображена на Рис.~\ref{fig:programm2/block-schema}, все возможные пути обозначены символами латинского алфавита от~A~до~I.

    Условия в ветвлениях программы:
    \begin{enumerate}
        \item $n$ целое число?
        \item $k$ целое число?
        \item $n < 1$;
        \item $n > 15$;
        \item $k < 1$;
        \item $k > 15$;
        \item $k \mod 2 = 1$;
        \item $k > 0$.
    \end{enumerate}


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

    Для покрытия всех операторов был составлен набор тестов из 4 тестов (Рис.~\ref{fig:programm2/table-operators}).

    \begin{figure}[h!]
       \centering
       \includegraphics[width=1\linewidth]{img/programm2/table-operators.png}
       \caption{Набор тестов для покрытия операторов программы.}
       \label{fig:programm2/table-operators}
    \end{figure}

    Для покрытия всех операторов программы достаточно было составить тесты для четырёх путей: A, BC, BDE, BDFHI.

    \newpage
    \subsubsection{Покрытие решений}
    В соответствии с этим критерием необходимо составить такой набор тестов, при котором каждое условие в программе примет как истинное, так и ложное значения. Таким образом, к тестам, составленным для метода покрытия операторов, необходимо добавить тесты, которые будут проверять все возможные переходы.

    Тесты, покрывающие все решения программы представлены на Рис.~\ref{fig:programm2/decision-coverage}.

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm2/decision-coverage.png}
        \caption{Набор тестов для покрытия решений программы.}
        \label{fig:programm2/decision-coverage}
    \end{figure}

    \subsubsection{Покрытие условий}
    В соответствии с этим критерием количество тестов должно быть таким, чтобы
    все возможные результаты каждого условия в решении выполнялись по крайней мере
    один раз.

    Тесты, покрывающие все условия программы представлены на Рис.~\ref{fig:programm2/condition-coverage}.

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm2/condition-coverage.png}
        \caption{Набор тестов для покрытия условий программы.}
        \label{fig:programm2/condition-coverage}
    \end{figure}
    
    \newpage
    \subsubsection{Покрытие решений и условий}
    Согласно этому критерию набор тестов является достаточно полным, если удовлетворяются следующие требования: каждое условие в решении принимает каждое
    возможное значение по крайней мере один раз, каждый возможный исход решения
    проверяется по крайней мере один раз и каждой точке входа управление передается
    по крайней мере один раз.

    Тесты, написанные ранее, обеспечивают покрытие решений и условий (Рис.~\ref{fig:programm2/condition-coverage-2}).

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm2/condition-coverage.png}
        \caption{Набор тестов для покрытия решений и условий программы.}
        \label{fig:programm2/condition-coverage-2}
    \end{figure}
    
    
    \newpage
    \subsubsection{Комбинаторное покрытие условий}
    Этот критерий требует создания такого набора тестов, при котором каждая возможная комбинация результатов вычисления условий в каждом решении и
    каждая точка входа проверяются по крайней мере один раз.

    Тесты, обеспечивающие комбинаторное покрытие условий, представлены на Рис.~\ref{fig:programm2/comb}.

    \begin{figure}[h!]
        \centering
        \includegraphics[width=1\linewidth]{img/programm2/comb.png}
        \caption{Набор тестов для комбинаторного покрытия условий программы.}
        \label{fig:programm2/comb}
    \end{figure}
    
    Покрыть истинную ветку условия 3 (путь B->D->E) невозможно из-за экстренного завершения программы при вводе строкового значения N.

    \subsubsection{Результаты тестирования методом <<белого ящика>>}
    В результате тестирования методом «белого ящика» было составлено 11 тестов. Программа прошла все 11 тестов. Это может говорить как о корректности программы, так и о том, что данный метод просто не подходит для тестирования данной программы, так как не рассматривает какую-либо ситуацию, в которой бы возникла ошибка.
    

    \newpage
    \subsection{Тестирование методом <<чёрного ящика>>}
    \subsubsection{Разбиение на классы эквивалентности}
    Составлено разбиение на классы эквивалентности исходя из ограничений для
    программы, представленное на Рис.~\ref{fig:programm2/classes}. Тесты для допустимых классов эквивалентности представлены на Рис.~\ref{fig:programm2/classes-test-dop} и тесты для недопустимых классов эквивалентности
    — на Рис.~\ref{fig:programm2/classes-test-nedop}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.6\linewidth]{img/programm2/classes.png}
       \caption{Разбиение на классы эквивалентности.}
       \label{fig:programm2/classes}
    \end{figure}
    
    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.75\linewidth]{img/programm2/classes-test-dop.png}
        \caption{Тесты для допустимых классов эквивалентности.}
        \label{fig:programm2/classes-test-dop}
    \end{figure}

    \begin{figure}[h!]
    \centering
    \includegraphics[width=0.75\linewidth]{img/programm2/classes-test-nedop.png}
    \caption{Тесты для недопустимых классов эквивалентности.}
    \label{fig:programm2/classes-test-nedop}
    \end{figure}

    Программа прошла все 9 тестов, составленных при рассмотрении классов эквивалентности входных данных.
    

    \newpage
    \subsubsection{Анализ граничных условий}
    В программе можно выделить следующие граничные условия:
    \begin{itemize}
        \item $n \geq 1$;
        \item $k \leq 15$;
        \item $n \geq 1$;
        \item $k \leq 15$.
    \end{itemize}
    
    Для каждой из границ определим тесты, соответствующие:
    \begin{itemize}
        \item граничному целому числу (верхнему/нижнему);
        \item целому числу, выходящему за границу (верхнюю/нижнюю) на единицу;
        % \item дробному числу, на 0.001 выходящему за границу (верхнюю/нижнюю).
    \end{itemize}
    
    Составленные тесты представлены на Рис.~\ref{fig:programm2/bounds}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.8\linewidth]{img/programm2/bounds.png}
       \caption{Тесты граничных условий.}
       \label{fig:programm2/bounds}
    \end{figure}

    При анализе граничных условий был составлен набор из 8 тестов. Программа прошла все 8 тестов.
    
    \newpage
    \subsubsection{Причинно-следственная диаграмма}

    \begin{figure}[h!]
        \centering
        \includegraphics[width=0.6\linewidth]{img/programm2/diagram.png}
        \caption{Причинно следственная диаграмма.}
        \label{fig:programm2/diagram}
     \end{figure}

    \textbf{Причины:}
    \begin{enumerate}
        \item $n$ -- целое число;
        % \item $n \geq 1$;
        \item $1 \leq n \leq 15$;
        % \item $k \geq 1$;
        \item $1 \leq k \leq 15$.
        \item $k$ -- целое число;
    \end{enumerate}
    
    \textbf{Промежуточные причины:}
    \begin{enumerate}
        \item[1.1] $n$ -- целое и $1 \leq n \leq 15$.
        \item[1.2] $k$ -- целое и $1 \leq k \leq 15$.
    \end{enumerate}
    
    \textbf{Следствия:}
    \begin{enumerate}
        \item[2.1] Программа выводит сообщение об ошибке ''Ошибка! n должно быть целым числом'' и заново запрашивает числа $n$ и $k$;
        \item[2.2] Программа выводит значение $n^k$ и завершает работу;
        \item[2.3] Программа выводит сообщение об ошибке ''Ошибка! Введите числа от 1 до 15'' и заново запрашивает числа $n$ и $k$;
        \item[2.4] Программа выводит сообщение об ошибке ''Ошибка! k должно быть целым числом'' и заново запрашивает числа $n$ и $k$;
    \end{enumerate}

    На Рис.~\ref{fig:programm2/diagram} представлена причинно-следственная диаграмма.

    Таблица решений для диаграммы представлена на Рис.~\ref{fig:programm2/table-decisions}.

    \begin{figure}[h!]
       \centering
       \includegraphics[width=0.5\linewidth]{img/programm2/table-decisions.png}
       \caption{Таблица решений.}
       \label{fig:programm2/table-decisions}
    \end{figure}

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

    \subsubsection{Результаты тестирования методом <<чёрного ящика>>}
    В результате тестирования методом чёрного ящика было составлено 17 тестов. Программа прошла все тесты. Это может свидетельствовать как о корректности программы, так и о том, что данный метод просто не подходит для данной программы, так как не рассматривает какую-либо ситуацию, в которой бы возникла ошибка.


    \newpage
    \section*{Заключение}
    \addcontentsline{toc}{section}{Заключение}
    В ходе выполнения данной лабораторной работы были изучены методологии модульного тестирования: метод <<белого ящика>> и метод <<чёрного ящика>>.

    При помощи изученных методологий были спроектированы тесты для  программы вычисления факториала числа и возведения числа в степень. При составлении тестов использовались методы:3
    \begin{itemize}
        \item Разбиения на классы эквивалентности;
        \item Анализа граничных значений;
        \item Причинно-следственной диаграммы;
        \item Критерия покрытия операторов;
        \item Критерия покрытия решений;
        \item Критерия покрытия условий;
        \item Критерия покрытия решений и условий;
        \item Критерия комбинаторного покрытия условий.
    \end{itemize}
    
    Тестирование проводилось с помощью комбинированного подхода: сначала проводилось тестирование методом «белого ящика», затем добавлялись тесты, основанные на методе «черного ящика».
    
    % Тестирование первой программы показало, что 11 тестов из 21, составленных методом чёрного ящика не были пройдены программой, и все 5 тестов, составленных методом белого ящика, были пройдены. Таким образом, сочетанием методов <<чёрного>> и <<белого>> ящиков удалось выявить ошибки в спецификации первой программы.
    
    При тестировании первой программы методом чёрного ящика не было пройдено 2 теста, методом белого ящика --- 1 тест. Ошибки, из-за которых тесты не были пройдены, связаны с некорректной проверкой входных значений и неверно составленной спецификацией.

    При тестировании второй программы методом чёрного ящика было составлено 17 тестов, методом белого ящика --- 11 тестов. В результате тестирования не удалось составить тест, который программа бы не прошла. Это может свидетельствовать как о корректности программы, так и о том, что данные методы просто не подходят для тестирования данной программы, так как не рассматривают какую-либо ситуацию, в которой бы возникла ошибка.
    
    Более эффективным методом для проверки программ оказался метод <<чёрного ящика>>. С его помощью удалось составить два теста, которые программа не смогла пройти. С помощью метода <<белого ящика>> удалось составить только один такой тест.
    
\newpage
\section*{Список литературы}
\addcontentsline{toc}{section}{Список литературы}

\vspace{-1.5cm}
\begin{thebibliography}{0}
    \bibitem{mayers}
    Майерс, Г. Искусство тестирования программ. -- Санкт-Петербург: Диалектика, 2012 г.
\end{thebibliography}

\end{document}