Особенности реализации

This commit is contained in:
2024-11-29 20:38:29 +03:00
parent 9e3e5cda0c
commit 25a5646093

View File

@@ -183,6 +183,100 @@
\newpage \newpage
\section {Особенности реализации} \section {Особенности реализации}
\subsection{Функция isCongruent}
Код функции для проверки числовой конгруэнтности представлен в листинге~\ref{lst:is-congruent}. Функция \texttt{isCongruent} принимает три числа: \texttt{a}, \texttt{b} и \texttt{d}. Она возвращает \texttt{True}, если остатки от деления \texttt{a} и \texttt{b} на \texttt{d} равны, и \texttt{False} в противном случае.
\begin{lstlisting}[caption={Функция для проверки числовой конгруэнтности.}, label={lst:is-congruent}]
isCongruent :: Int -> Int -> Int -> Bool
isCongruent a b d = a `mod` d == b `mod` d
\end{lstlisting}
\subsection{Функция filterByPredicate}
Код функции для фильтрации элементов списка на основе предиката представлен в листинге~\ref{lst:filter-by-predicate}. Функция \texttt{filterByPredicate} принимает предикат (\texttt{predicate}) и список (\texttt{[a]}). Она возвращает новый список, содержащий только те элементы исходного списка, для которых предикат возвращает \texttt{True}.
\begin{lstlisting}[caption={Функция для фильтрации списка по предикату.}, label={lst:filter-by-predicate}]
filterByPredicate :: (a -> Bool) -> [a] -> [a]
filterByPredicate _ [] = []
filterByPredicate predicate (x:xs)
| predicate x = x : filteredTail
| otherwise = filteredTail
where
filteredTail = filterByPredicate predicate xs
\end{lstlisting}
\subsection{Тесты для функции isCongruent}
Для тестирования функции \texttt{isCongruent} использовались свойства, проверяемые с использованием библиотеки QuickCheck. Ниже приведены описания тестов, представленных в листинге~\ref{lst:congruent-tests}.
\begin{itemize}
\item \texttt{propCongruentDifference}: Проверяет, что два числа конгруэнтны по модулю \texttt{m}, если и только если разность этих чисел делится на \texttt{m} без остатка.
\item \texttt{propCongruentSymmetric}: Проверяет симметричность конгруэнтности, то есть, если \texttt{a} конгруэнтно \texttt{b}, то \texttt{b} конгруэнтно \texttt{a}.
\item \texttt{propCongruentEqualNumbers}: Проверяет, что любое число \texttt{a} всегда конгруэнтно самому себе по любому ненулевому модулю.
\end{itemize}
\begin{lstlisting}[caption={Тесты для функции \texttt{isCongruent} с использованием QuickCheck.}, label={lst:congruent-tests}]
propCongruentDifference :: Int -> Int -> Int -> Property
propCongruentDifference a b m =
m /= 0 ==> isCongruent a b m == ((a - b) `mod` m == 0)
propCongruentSymmetric :: Int -> Int -> Int -> Property
propCongruentSymmetric a b m =
m /= 0 ==> isCongruent a b m == isCongruent b a m
propCongruentEqualNumbers :: Int -> Int -> Property
propCongruentEqualNumbers a m =
m /= 0 ==> isCongruent a a m == True
\end{lstlisting}
\subsection{Тесты для функции filterByPredicate}
Для тестирования функции \texttt{filterByPredicate} использовались свойства, проверяемые с использованием библиотеки QuickCheck. Описание тестов приведено в листинге~\ref{lst:filter-tests}.
\begin{itemize}
\item \texttt{propFilterByPredicateSatisfiesPredicate}: Проверяет, что все элементы результирующего списка удовлетворяют переданному предикату.
\item \texttt{propFilterByPredicateLength}: Проверяет, что длина результирующего списка не превышает длину исходного списка.
\item \texttt{propFilterByPredicateAlwaysTrue}: Проверяет, что если предикат всегда возвращает \texttt{True}, результирующий список совпадает с исходным.
\end{itemize}
\begin{lstlisting}[caption={Тесты для функции \texttt{filterByPredicate} с использованием QuickCheck.}, label={lst:filter-tests}]
propFilterByPredicateSatisfiesPredicate :: Fun Int Bool -> [Int] -> Bool
propFilterByPredicateSatisfiesPredicate (Fun _ predicate) xs =
all predicate (filterByPredicate predicate xs)
propFilterByPredicateLength :: Fun Int Bool -> [Int] -> Bool
propFilterByPredicateLength (Fun _ predicate) xs =
length (filterByPredicate predicate xs) <= length xs
propFilterByPredicateAlwaysTrue :: [Int] -> Bool
propFilterByPredicateAlwaysTrue xs =
filterByPredicate (\_ -> True) xs == xs
\end{lstlisting}
\subsection{Запуск тестов}
Для выполнения всех тестов в проекте создан файл \texttt{Spec.hs}, в котором определена функция \texttt{main}. Она последовательно запускает все тесты, используя библиотеку \texttt{QuickCheck}. Код функции \texttt{main} приведён в листинге~\ref{lst:test-main}.
Функция \texttt{quickCheck} используется для автоматического тестирования свойств. Она генерирует случайные входные данные, проверяет выполнение свойства на каждом из них и сообщает о результатах. В случае провала теста \texttt{quickCheck} предоставляет пример данных, на которых свойство не выполняется.
Для сборки проекта и выполнения всех тестов достаточно выполнить команду \texttt{stack test}.
\begin{lstlisting}[caption={Функция \texttt{main} для запуска тестов.}, label={lst:test-main}]
main :: IO ()
main = do
quickCheck propCongruentDifference
quickCheck propCongruentSymmetric
quickCheck propCongruentEqualNumbers
quickCheck propFilterByPredicateSatisfiesPredicate
quickCheck propFilterByPredicateLength
quickCheck propFilterByPredicateAlwaysTrue
\end{lstlisting}
\newpage \newpage