Практическая работа № 1 - Северо

advertisement
ИНФОРМАЦИОННЫЕ СИСТЕМЫ
И ТЕХНОЛОГИИ
Часть II
Методические указания
к практическим работам
Для студентов, обучающихся по направлению подготовки
230700.62 – «Прикладная информатика»
Составители:
С. Б. Волошин, С. Э. Бурдунова,
С. В. Селезнев, Д. А. Дегтярева
Владикавказ 2015
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ
Федеральное государственное бюджетное образовательное
учреждение высшего образования
«СЕВЕРО-КАВКАЗСКИЙ ГОРНО-МЕТАЛЛУРГИЧЕСКИЙ ИНСТИТУТ
(ГОСУДАРСТВЕННЫЙ ТЕХНОЛОГИЧЕСКИЙ УНИВЕРСИТЕТ)»
Кафедра «Информационные системы в экономике»
ИНФОРМАЦИОННЫЕ СИСТЕМЫ
И ТЕХНОЛОГИИ
Часть II
Методические указания
к практическим работам
Для студентов, обучающихся по направлению подготовки
230700.62 – «Прикладная информатика»
Составители:
С. Б. Волошин, С. Э. Бурдунова,
С. В. Селезнев, Д. А. Дегтярева
Владикавказ 2015
1
УДК 004
ББК 73
В68
В68
Информационные системы и технологии. Часть II. Методические указания к практическим работам. Для студентов, обучающихся по направлению подготовки 230700.62 – «Прикладная информатика» / Сост.: С. Б. Волошин, С. Э. Бурдунова, С. В. Селезнев, Д. А. Дегтярева; Северо-Кавказский горно-металлургический
институт (государственный технологический университет). –
Владикавказ: Северо-Кавказский горно-металлургический институт
(государственный технологический университет). Изд-во «Терек»,
2015. – 46 с.
УДК 004
ББК 73
Редактор: Иванченко Н. К.
Компьютерная верстка: Кравчук Т. А.
 Составление. ФГБОУ ВО «Северо-Кавказский
горно-металлургический институт (государственный
технологический университет)», 2015
 Волошин С. Б., Бурдунова С. Э., Селезнев С. В.,
Дегтярева Д. А.; составление, 2015
Подписано в печать 22.07.15. Формат бумаги 60х84 1/16. Бумага офсетная. Гарнитура «Таймс».
Печать на ризографе. Усл. п.л. 2,67. Уч.-изд.л. 1,77. Тираж 10 экз. Заказ № ____.
Северо-Кавказский горно-металлургический институт (государственный
технологический университет). Изд-во «Терек».
Отпечатано в отделе оперативной полиграфии СКГМИ (ГТУ).
362021. Владикавказ, ул. Николаева, 44.
2
Оглавление
Практическая работа № 1 .................................................................... 4
Практическая работа № 2 .................................................................... 7
Практическая работа № 3 .................................................................... 11
Практическая работа № 4 .................................................................... 17
Практическая работа № 5 .................................................................... 22
Практическая работа № 6 .................................................................... 31
Литература ............................................................................................ 46
3
Практическая работа №1
ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ ЭЛЕМЕНТОВ
УПРАВЛЕНИЯ RichTextBox, ToolStrip, OpenFileDialog
И SaveFileDialog
Цель работы: научиться использовать элементы управления для
ввода и редактирования форматированного текста большего объема,
элементы управления командами и инструменты выбора пути для открытия и сохранения файлов.
Выполнение практической работы
Во время выполнения практической работы необходимо написать
программу, которая позволяет вводить с клавиатуры в элемент управления RichTextBox форматированный текст, сохранять введенный
текст в формате RTF на цифровой носитель (жесткий диск, флэшнакопитель и т. д.) с использованием стандартного диалогового окна
«Сохранить файл», считывать из файла и записывать в RichTextBox
файл в формате RTF.
Используемые элементы управления описаны в табл. 1.1.
Таблица 1.1
№
1
1
Тип элемента
2
Form
2
3
ToolStrip
ToolStripButton
4
ToolStripButton
Устанавливаемые свойства
3
Name = “frmMain”
Text = “Практическая работа
№1”
StartPosition = “CenterScreen”
Name = “ToolStripMain”
Name = “cmdOpen”
Text = “Открыть”
DisplayStyle = “ImageAndText”
Image = “Open.png”
Name = “cmdSave”
Text = “Сохранить”
DisplayStyle = “ImageAndText”
Image = “Save.png”
4
Окончание табл. 1.1
1
5
2
ToolStripButton
6
RichTextBox
3
Name = “cmdExit”
Text = “Выход”
DisplayStyle = “ImageAndText”
Image = “Exit.png”
Alignment = “Right”
Name = “rtbText”
Dock = “Fill”
Интерфейс главного окна приложения приведен на рис. 1.1.
Рис. 1.1. Главное окно приложения
Полный исходный код лабораторной работы приведен в листинге 1.1.
Листинг 1.1
PublicClassfrmMain
PrivateSubcmdOpen_Click(senderAsSystem.Object, _
eAsSystem.EventArgs) HandlescmdOpen.Click
DimmyOpenFileDialogAsNewOpenFileDialog
myOpenFileDialog.Filter = "Файлывформате RTF|*.rtf"
5
IfmyOpenFileDialog.ShowDialog = _
Windows.Forms.DialogResult.OKThen
Try
rtbText.LoadFile(myOpenFileDialog.FileName)
CatchexAsException
MessageBox.Show("Ошибкаоткрытияфайла!")
EndTry
EndIf
EndSub
PrivateSubcmdSave_Click(senderAsSystem.Object, _
eAsSystem.EventArgs) HandlescmdSave.Click
DimmySaveFileDialogAsNewSaveFileDialog
mySaveFileDialog.Filter = "Файлывформате RTF|*.rtf"
mySaveFileDialog.DefaultExt = "rtf"
IfmySaveFileDialog.ShowDialog = _
Windows.Forms.DialogResult.OKThen
Try
rtbText.SaveFile(mySaveFileDialog.FileName)
CatchexAsException
MessageBox.Show("Ошибкасохраненияфайла!")
EndTry
EndIf
EndSub
PrivateSubcmdExit_Click(senderAsSystem.Object, _
eAsSystem.EventArgs) HandlescmdExit.Click
Application.Exit()
EndSub
EndClass
Вопросы к практической работе
1. Какие значения может принимать свойство DisplayStyle
элемента управления ToolStripButton? Чем отличаются эти значения?
2. Какие значения может принимать свойство Dock? Чем отличаются эти значения?
3. В каком формате сохраняются данные, вводимые в RichTextBox? Каким приложением можно открыть файлы данного формата?
4. Какой метод используются для вывода на экран диалоговых
окон OpenFileDialogи SaveFileDialog?
6
П р а к т и ч е с к а я р а б о т а №2
РАБОТА С ХЭШ-ФУНКЦИЯМИ
Цель работы: научиться работать с алгоритмами для вычисления
хэш-функций MD5, SHA-1, SHA-256, SHA-384 и SHA-512.
Выполнение практической работы
Во время выполнения практической работы необходимо написать
программу, которая позволяет вычислять следующие хэш-функции
введенного в текстовое окно исходного текста:
1. MD5.
2. SHA-1.
3. SHA-256.
4. SHA-384.
5. SHA-512.
Рис. 2.1. Внешний вид приложения для работы с хэш-функциями
7
1. Спроектировать графический интерфейс приложения.
2. Текстовые окна ReadOnly = True
Листинг 2.1
Imports System.Security.Cryptography
Imports System.Text
Public Class frmHash
''' Вычисляем хэш
Private Sub cmdHash_Click(sender As System.Object, _
e As System.EventArgs) Handles cmdHash.Click
If txtSourceText.Text.Length = 0 Then
'Выводим сообщением, что окно пустое
MessageBox.Show("Введите исходный текст")
Else
'считываем исходный текст из текстового окна
Dim SourceText As String = txtSourceText.Text
'-------------------MD5------------------------'объявляем крипто-провайдер
Dim md5Provider As New MD5CryptoServiceProvider
'объявляем строковую переменную и рассчитываем MD5-хэш
Dim MD5Hash As String = Convert.ToBase64String(_
md5Provider.ComputeHash(UTF8Encoding.UTF8.GetBytes(_
SourceText)))
'Выводим хэш в текстовое окно
txtMD5.Text = MD5Hash
'-------------------SHA-1------------------------'объявляем менеджер SHA-1
Dim SHA1Manager As New SHA1Managed
'объявляем строковую переменную и рассчитываем SHA-1хэш
Dim SHA1Hash As String = Convert.ToBase64String(_
SHA1Manager.ComputeHash(UTF8Encoding.UTF8.GetBytes(_
SourceText)))
'Выводим хэш в текстовое окно
8
txtSHA1.Text = SHA1Hash
'-------------------SHA-256------------------------'объявляем менеджер SHA-256
Dim SHA256Manager As New SHA256Managed
'объявляем строковую переменную и рассчитываем SHA-256хэш
Dim SHA256Hash As String = Convert.ToBase64String(_
SHA256Manager.ComputeHash(UTF8Encoding.UTF8.GetBytes(_
SourceText)))
'Выводим хэш в текстовое окно
txtSHA256.Text = SHA256Hash
'-------------------SHA-384------------------------'объявляем менеджер SHA-384
Dim SHA384Manager As New SHA384Managed
'объявляем строковую переменную и рассчитываем SHA-256хэш
Dim SHA384Hash As String = Convert.ToBase64String(_
SHA384Manager.ComputeHash(UTF8Encoding.UTF8.GetBytes(_
SourceText)))
'Выводим хэш в текстовое окно
txtSHA384.Text = SHA384Hash
'-------------------SHA-512------------------------'объявляем менеджер SHA-512
Dim SHA512Manager As New SHA512Managed
'объявляем строковую переменную и рассчитываем SHA-512хэш
Dim SHA512Hash As String = Convert.ToBase64String(_
SHA512Manager.ComputeHash(UTF8Encoding.UTF8.GetBytes(_
SourceText)))
'Выводим хэш в текстовое окно
txtSHA512.Text = SHA512Hash
End If
End Sub
''' Очищаем текстовые окна
9
Private Sub cmdClear_Click(sender As System.Object, _
e As System.EventArgs) Handles cmdClear.Click
txtSourceText.Clear()
txtMD5.Clear()
txtSHA1.Clear()
txtSHA256.Clear()
txtSHA384.Clear()
txtSHA512.Clear()
End Sub
''' Выход
Private Sub cmdExit_Click(sender As System.Object, _
e As System.EventArgs) Handles cmdExit.Click
Application.Exit()
End Sub
End Class
Вопросы к практической работе
1. Опишите принципы работы асимметричных алгоритмов шифрования.
2. Приведите примеры наиболее распространенных асимметричных алгоритмов шифрования.
3. Опишите, для каких целей используются открытый и закрытый ключи шифрования.
4. Опишите предназначение класса RSACryptoServiceProvider.
5. Опишите работу функций Encryptи Decrypt класса
RSACryptoServiceProvider.
10
Практическая работа №3
РАБОТА С АСИММЕТРИЧНЫМ
КРИПТОГРАФИЧЕСКИМ АЛГОРИТМОМ RSA
Цель работы: ознакомиться с особенностями криптографического алгоритма RSA и его реализацией в Microsoft .NETFramework на
языке программирования MicrosoftVisualBasic 2010.
Введение
Начало асимметричным шифрам было положено в работе «Новые
направления в современной криптографии» Уитфилда Диффи и Мартина Хеллмана, опубликованной в 1976 году. Находясь под влиянием
работы Ральфа Меркле о распространении открытого ключа, они
предложили метод получения секретных ключей, используя открытый
канал. Этот метод экспоненциального обмена ключей, который стал
известен как обмен ключами Диффи – Хеллмана, был первым опубликованным практичным методом для установления разделения секретного ключа между заверенными пользователями канала. В 2002 году
Хеллман предложил называть данный алгоритм «Диффи – Хеллмана –
Меркле», признавая вклад Меркле в изобретение криптографии с открытым ключом. Эта же схема была разработана Малькольмом Вильямсоном в 1970-х, но держалась в секрете до 1997 года. Метод Меркле
по распространению открытого ключа был изобретён в 1974 и опубликован в 1978 году, его также называют загадкой Меркле.
Асимметричные методы используют два взаимосвязанных ключа:
для шифрования и расшифрования. Один ключ является закрытым
(секретным) и известным только получателю. Его используют для
расшифрования. Второй из ключей является открытым (несекретным), т. е. он может спокойно передаваться по незащищенным каналам связи и быть опубликован, например, вместе с адресом пользователя. Его используют для выполнения шифрования.
Формально асимметричный метод можно описать следующим
образом. Обозначим результат шифрования текста T с помощью открытого ключа – E(T), а результат расшифровки текста с помощью
закрытого ключа – D(T). Тогда асимметричный метод должен отвечать следующим трем требованиям:
 D(E(T)) = T;
 D практически невозможно определить по E;
 Е нельзя взломать.
11
Преимущество указанного метода состоит в уменьшении количества ключей, с которыми приходится оперировать. Однако данный
алгоритм имеет существенный недостаток – требует значительной вычислительной мощности. Использование асимметричного метода
шифрования представлено на рис. 3.1.
Рис. 3.1. Использование асимметричного метода шифрования
с открытым ключом
В настоящее время наиболее известными и надежными являются
следующие асимметричные алгоритмы:
 алгоритм RSA (Rivest, Shamir, Adleman);
 алгоритм Эль Гамаля (Elgamal);
 ГОСТ Р 34.10-2001.
Алгоритм RSA принят в качестве следующих международных
стандартов: ISO/IEC/DIS 9594-8 и X.509. Алгоритм использует факт,
что нахождение больших (например, 100-битных) простых чисел в
вычислительном отношении осуществляется легко, однако разложение на множители произведения двух таких чисел в вычислительном
отношении представляется невыполнимым.
В настоящее время Международная сеть электронного перечисления
платежей SWIFT требует от банковских учреждений, пользующихся
ее услугами, применения именно этого алгоритма криптографического преобразования информации.
Алгоритм работает так:
1. Отправитель выбирает два очень больших простых числа P и
Q и вычисляет два произведения N = PQ и M = (P-1)(Q-1).
2. Затем он выбирает случайное целое число D, взаимно простое
с M, и вычисляет E, удовлетворяющее условию DE = 1 mod M.
12
3. После этого он публикует D и N как свой открытый ключ
шифрования, сохраняя E как закрытый ключ.
4. Если S – сообщение, длина которого, определяемая по значению выражаемого им целого числа, должна быть в интервале (1, N), то
оно превращается в шифровку возведением в степень D по модулю N
и отправляется получателю S1 = SD mod N.
5. Получатель сообщения расшифровывает его, возводя в степень E по модулю N, так как S = S1E mod N = SDE mod N.
Таким образом, открытым ключом служит пара чисел N и D, а
секретным ключом число E.Смысл этой системы шифрования основан
на так называемой малой теореме Ферма, которая утверждает, что
при простом числе P и любом целом числе K, которое меньше P,
справедливо тождество
KP-1 = 1 modP.
Эта теорема позволяет определить, является ли какое-либо число
простым или составным.
Выполнение практической работы
Во время выполнения практической работы необходимо написать
программу, которая позволяет:
1. Генерировать открытый и закрытый ключи алгоритма RSAи
записывать их в файлы в формате XML.
2. Считывать ключи из файлов.
3. Осуществлять шифрование текстовой информации.
4. Сохранять зашифрованную информацию в файл.
5. Считывать зашифрованную информацию из файла.
6. Осуществлять расшифрование зашифрованной информации.
Главное окно приложения представлено на рис. 3.2.
Рис. 3.2. Главное окно приложения
13
Используемые элементы управления описаны в табл. 3.1.
Таблица 3.1
№
1
1
Тип элемента
2
Form
2
Button
3
Button
4
Button
5
Button
6
Button
7
Button
8
TextBox
9
TextBox
10
Label
11
Label
Устанавливаемые свойства
3
Name = “frmRSA”
Text = “Шифрование с помощью алгоритма
RSA”
Name = “cmdGenAndSave”
Text = “Генерировать ключи и записать
их в файл”
Name = “cmdLoadKeysFromFiles”
Text = “Считатьключиизфайла”
Name = “cmdCrypt”
Text = “Шифровать”
Name = “cmdDecrypt”
Text = “Расшифровать”
Name = “cmdToFile”
Text = “Записать в файл”
Name = “cmdFromFile”
Text = “Считать из файла”
Name = “txtEncryptText”
Text = “”
Name = “txtResult”
Text = “”
Name = “lblEncryptText”
Text = “Введите текст, который будете
шифровать”
Name = “lblResult”
Text = “Зашифрованный текст”
Исходный код программы приведен в листинге 3.1.
Листинг 3.1
Imports System.Security.Cryptography
Imports System.Text
Imports System.Xml
Public Class frmRSA
Dim EK As String = ""
Dim DK As String = ""
Dim cspParam As CspParameters
14
Private Sub cmdGenAndSave_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdGenAndSave.Clic
k
Dim rsaProvider As New RSACryptoServiceProvider()
EK = rsaProvider.ToXmlString(False)
DK = rsaProvider.ToXmlString(True)
My.Computer.FileSystem.WriteAllText("C:\EK.xml", EK, Fa
lse)
My.Computer.FileSystem.WriteAllText("C:\DK.xml", DK, Fa
lse)
End Sub
Private Sub cmdLoadKeysFromFiles_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmdLoadKeysFromFiles.Click
EK = My.Computer.FileSystem.ReadAllText("C:\EK.xml")
DK = My.Computer.FileSystem.ReadAllText("C:\DK.xml")
End Sub
Private Sub cmdCrypt_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdCrypt.Click
Dim rsaProvider = New RSACryptoServiceProvider(cspParam
)
rsaProvider.FromXmlString(EK)
Dim cipheredText As Byte() = rsaProvider.Encrypt(_
UTF8Encoding.UTF8.GetBytes(txtEncryptText.Text), True)
Dim EncodingText As String = Convert.ToBase64String(_
cipheredText)
txtResult.Text = EncodingText
End Sub
Private Sub cmdDecrypt_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdDecrypt.Click
Dim rsaProvider = New RSACryptoServiceProvider(cspParam
)
rsaProvider.FromXmlString(DK)
Dim EncodingText As String = txtResult.Text
Dim DecodingText As String = ""
DecodingText = UTF8Encoding.UTF8.GetString(_
15
rsaProvider.Decrypt(Convert.FromBase64String(_
EncodingText), True))
txtEncryptText.Text = DecodingText
End Sub
Private Sub frmRSA_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
cspParam = New CspParameters()
cspParam.KeyContainerName = "aaa13bbb"
End Sub
Private Sub cmdToFile_Click(ByVal sender As System.Object,
_
ByVal e As System.EventArgs) Handles cmdToFile.Click
My.Computer.FileSystem.WriteAllText("C:\info.crypt", _
txtResult.Text, False)
End Sub
Private Sub cmdFromFile_Click(_
ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdFromFile.Click
txtResult.Text = My.Computer.FileSystem.ReadAllText(_
"C:\info.crypt")
End Sub
End Class
Вопросы к практической работе
1. Опишите принципы работы асимметричных алгоритмов шифрования.
2. Приведите примеры наиболее распространенных асимметричных алгоритмов шифрования.
3. Опишите, для каких целей используются открытый и закрытый ключи шифрования.
4. Опишите предназначение класса RSACryptoServiceProvider.
5. Опишите работу функций Encryptи Decrypt класса
RSACryptoServiceProvider.
16
Практическая работа №4
РАБОТА С СИММЕТРИЧНЫМ
КРИПТОГРАФИЧЕСКИМ АЛГОРИТМОМ AES (Rijndael)
Цель работы: ознакомиться с особенностями криптографического алгоритма AES (Rijndael) и его реализацией в Microsoft .NET
Framework на языке программирования MicrosoftVisualBasic 2010.
Введение
В симметричных методах для шифрования и расшифровывания
используется один и тот же секретный ключ.
Общая технология использования симметричного метода шифрования представлена на рис. 4.1.
Рис. 4.1. Использование симметричного метода шифрования
К достоинствам симметричных методов относят высокое быстродействие и простоту.
Основным недостатком указанных методов является то, что ключ
должен быть известен и отправителю, и получателю. Это существенно
усложняет процедуру назначения и распределения ключей между
пользователями. По существу, в открытых сетях должен быть предусмотрен физически защищенный канал передачи ключей.
17
Названный недостаток послужил причиной разработки методов
шифрования с открытым ключом – асимметричных методов.
В 1997 г. NIST (National Institute of Standards and Technology)
анонсировал конкурс на создание AES (Advanced Encryption Standard) – нового государственного криптографического стандарта США.
Тогда же были оговорены следующие первичные требования, которым должен удовлетворять AES: это должен быть незасекреченный,
открыто опубликованный алгоритм шифрования, бесплатно доступный по всему миру. Спустя некоторое время было уточнено, что AES
должен быть блочным шифром, реализующим криптографическую
процедуру с симметричным ключом, причем алгоритм (как минимум)
должен поддерживать 128-битную длину шифруемого блока текста и
длины ключей 128, 192 и 256 бит.
В 2000 г. в конкурсе победил алгоритм Rijndael, предложенный
бельгийскими криптоаналитиками Джоаном Дайеменом (JoanDaemen)
и Винсентом Риджеменом (VincentRijmen).
В настоящее время подавляющее большинство применяемых на
практике симметричных систем с закрытым (секретным) ключом
представляют собой блочные системы, которые задают параметризованное ключом преобразование блоков исходного сообщения (как
правило, длиной 64 бита) в блоки шифрограммы. Алгоритм Rijndael
не является исключением.
При блочном шифровании открытый текст сначала разбивается
на равные по длине блоки, затем применяется зависящая от ключа
функция шифрования для преобразования блока открытого текста
длиной mбит в блок шифр текста такой же длины.
Достоинством блочного шифрования является то, что каждый бит
блока шифр текста зависит от значений всех битов соответствующего
блока открытого текста, и никакие два блока открытого текста не
могут быть представлены одним и тем же блоком шифр текста.
Поэтому в настоящее время подавляющее большинство применяемых
на практике как симметричных систем с закрытым (секретным)
ключом, так и асимметричных систем с открытым ключом,
представляют собой блочные системы, как правило, с длиной блоков в
64 бита.
Выполнение практической работы
Во время выполнения практической работы необходимо написать
программу, которая позволяет:
18
1. Осуществлять шифрование текстовой информации с помощью
алгоритма Rijndael при нажатии на кнопку «Зашифровать».
2. Осуществлять расшифрование зашифрованной информации с
помощью алгоритма Rijndael при нажатии на кнопку «Расшифровать».
Главное окно приложения представлено на рис. 4.2.
Рис. 4.2. Главная форма приложения
Используемые элементы управления описаны в табл. 4.1.
Таблица 4.1
№
1
Тип элемента
Form
2
Button
3
Button
8
TextBox
10
Label
Устанавливаемые свойства
Name = “frmRijndael”
Text =
“ШифрованиеспомощьюалгоритмаRijndael”
Name = “cmdEncrypt”
Text = “Зашифровать”
Name = “cmdDecrypt”
Text = “Расшифровать”
Name = “txtEncryptText”
Text = “”
Name = “lblEncryptText”
Text = “Введите текст, который будете
шифровать”
Исходный код программы приведен в листинге 4.1.
Листинг 4.1
Imports System.Security.Cryptography
Imports System.Text
Imports System.IO
Public Class frmRijndael
Dim RijndaelManager As New RijndaelManaged()
19
Private Sub cmdEncrypt_Click(sender As System.Object, _
e As System.EventArgs) Handles cmdEncrypt.Click
Dim memStream As New MemoryStream()
Dim encStream As New CryptoStream(memStream, _
RijndaelManager.CreateEncryptor(), CryptoStreamMode.Write)
Dim sw As New StreamWriter(encStream)
sw.WriteLine(txtEncrypt.Text)
sw.Close()
encStream.Close()
My.Computer.FileSystem.WriteAllBytes("C:\myFile.data",
_
memStream.ToArray(), False)
memStream.Close()
End Sub
Private Sub cmdDecrypt_Click(sender As System.Object, _
e As System.EventArgs) Handles cmdDecrypt.Click
Dim buffer As Byte() = _
My.Computer.FileSystem.ReadAllBytes("C:\myFile.data")
Dim memStream As New MemoryStream(buffer)
Dim decStream As New CryptoStream(memStream, _
RijndaelManager.CreateDecryptor(), CryptoStreamMode.Read)
Dim sr As New StreamReader(decStream)
txtEncrypt.Text = sr.ReadToEnd()
sr.Close()
decStream.Close()
memStream.Close()
End Sub
Private Sub frmRijndael_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
'указываемключ
RijndaelManager.Key = New Byte() {1, 2, 3, 4, 5, 6, 7, 8, _
9, 10, 11, 12, 13, 14, 15, 16}
'указываемвекторинициализации
RijndaelManager.IV = New Byte() {1, 2, 3, 4, 5, 6, 7, 8, _
9, 10, 11, 12, 13, 14, 15, 16}
End Sub
End Class
20
Вопросы к практической работе
1. Опишите принципы работы симметричных алгоритмов шифрования.
2. Приведите примеры наиболее распространенных симметричных алгоритмов шифрования.
3. Опишите предназначение класса RijndaelManaged.
4. Опишите работу функций CreateEncryptor и CreateDecryptor класса RijndaelManaged.
21
Практическая работа №5
ТЕСТИРОВАНИЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Цель работы: ознакомиться с основными понятиями процесса
тестирования программного обеспечения и его проведением в средах
MicrosoftVisualStudio 2010 UltimateиMicrosoftTestManager 2010.
1. Общее описание процесса тестирования
Тестирование программного обеспечения – это процесс проверки
разработанного программного продукта на соответствие реального
поведения программы ожидаемому. Таким образом, тестирование ПО
– это контроль качества разрабатываемого продукта. Контроль качества особенно важен при разработке защищенных (особо важных) информационных систем.
Для организации процесса тестирования составляется тест-план и
тест-стратегия. Тест план – это документ, описывающий объем работ
по проведению тестирования, в нем отражаются общие цели и задачи
тестирования. Тест-стратегия представляет собой документ, описывающий конкретные техники тестирования.
Тест-стратегия включает в себя список тестовых случаев (TestCases). В средах MicrosoftVisualStudio 2010 Ultimate и
MicrosoftTestManager 2010 тестовый случай –это рабочий элемент,
состоящий из совокупности шагов, условий, а также параметров, необходимых для проверки корректности работы тестируемой функции.
После проведения тестирования формируется отчетная документация (отчет по тестированию программного продукта).
2. Тест-план
Тест-план составляется менеджером проекта. Тест-план должен
включать в себя ответы на следующие вопросы:
 Что представляет собой система (сведения о продукте, его
назначение)?
 Какие части продукта будут протестированы?
 Потенциальные риски продукта (какие слабые места могут
быть у продукта).
 В какие сроки пройдет тестирование? (Указывается, какие виды тестирования (см. описание тест-стратегии) будут проходить на
той или иной стадии (итерации) разработки продукта)?
22
 Кто будет тестировать?
Как правило, ответственным за проведение тестирования по
тестовым случаям (конфигурационное и интеграционное), Usability- и Exploratory-тестирование назначается тестировщик.
Как правило, ответственным за проведение Unit-тестирования
назначается разработчик тестируемой части программы, а
тестирования производительности – один из разработчиков
продукта.
Как правило, ответственным за проведение приемочного тестирования назначается бизнес-аналитик.
 Критерии окончания тестирования.
Составим тест-план для тестирования программы, разработанной
в процессе выполнения лабораторной работы № 13.
Пример тест-плана для программы «Алгоритм Rijndael»:
1. Что представляет из себя система (сведения о продукте, его
назначение)?
Программа«Алгоритм Rijndael» представляет собой WinFormsприложение, предназначенное для шифрования данных. Данное приложение может использоваться двумя типами пользователей – это
человек, который зашифровывает данные (Шифровщик), и человек,
который расшифровывает данные (Дешифровщик). Шифровщик
может с помощью программы зашифровать данные. Дешифровщик
может с помощью программы расшифровать уже зашифрованные с
помощью алгоритма Rijndael данные.
2. Какие части продукта будут протестированы?
Программа состоит из одного модуля, выполняющего как функцию шифрования, так и функцию дешифрования. Протестирован будет данный модуль.
3. Потенциальные риски продукта (какие слабые места могут
быть у продукта).
Основным риском тестируемой системы является риск некорректной зашифровки и расшифровки данных.
4. В какие сроки пройдет тестирование?
После завершения разработки программы необходимо провести
конфигурационное
тестирование,
usability-тестирование,
23
exploratory-тестирование и приемочное тестирование. В связи с малым масштабом и низкой сложностью системы на процесс тестирования отводится 1 час 30 минут.
5. Кто будет тестировать?
Ответственным за проведение тестирования назначается тестировщик.
6. Критерии окончания тестирования.
Тестирование считается завершенным, если были проведены и
успешно завершены все предусмотренные тест – стратегией виды
тестирования.
3. Тест-стратегия
В тест-стратегии указывается, какие виды тестирования будут
проведены, указываются конфигурация платформ, на которых проводится тестирование и инструменты, с помощью которых проводится
тестирование, а также список TestCases.
3.1. Виды тестирования
Интеграционное тестирование – этот вид тестирования проверяет взаимодействие компонентов, взаимодействие модулей, которые
общаются между собой. Тестирование проводится с помощью нескольких TestCases из общего набора, которые относятся к интеграции.
Конфигурационное тестирование – проверка работоспособности системы в различных конфигурациях программного и аппаратного
обеспечения (оперативная память, процессор, видео-карта и т. п.). Для
проведения такого вида тестирования нужно провести тестирование
по всем TestCases на одной конфигурации (например, браузер/ОС),
записать и автоматически воспроизвести на других конфигурациях.
Тестирование производительности – тестирование системы
при идеальных условиях и максимальной нагрузке. Например, обзоры
аппаратной части компьютера (процессоров, видеокарт, жестких дисков и др.), когда в качестве нагрузки работают программные приложения, после чего анализируются получаемые результаты. Ответственным за этот вид тестирования может быть назначен один из разработчиков проекта. Тестирование производительности может включать следующие направления:
24
– нагрузочное тестирование – это тестирование производительности, за исключением того, что система подвергается различным
нагрузкам. Цель этого вида тестирования – определить, как поведет
себя система в случае, когда планируемая нагрузка превышена;
– объёмное тестирование – тестирование при большом количестве данных. Его цель – определить, при каких объёмах данных система перестаёт работать;
– стресс-тестирование – тестирование при недостатке ресурсов,
когда не хватает ресурсов железа, например, оперативной памяти, места на жестком диске, ширины пропускного канала сети и т. д.;
– модульное тестирование – проверка функционирования самого элементарного компонента системы. Обычно берется самый минимально возможный для тестирования компонент – одна функция программы;
– приёмочное тестирование – это тестирование продукта на соответствие требованиям. Требования выдвигаются заказчиками. Ответственным за приемочное тестирование обычно назначается бизнесаналитик. Проводится после того, как был реализован пользовательский интерфейс и/или добавлена новая функциональность, а также на
заключительном этапе разработки;
– exploratory-тестирование – это тестирование методом свободного поиска, или тестирование без заранее спроектированных тестов,
выполняемых в точном соответствии с планом;
– usability-тестирование – предназначено для тестирования
удобства и простоты пользования программой. Проводится не по
TestCases, представляет собой оценку в целом. Обычно имеется ряд
вопросов-критериев, на которые можно ориентироваться при оценке
usability системы.
В процессе разработки продукта необходимо проводить регрессионное тестирование одного или нескольких видов тестирования.
Регрессионное тестирование – повторное. С его помощью проверяют исправления в программе. Например, есть дефект. Его исправляют, после чего проводят регрессионный тест, т. е. проверяют, исправлена ли ошибка на самом деле или нет. Данный набор действий
необходимо выполнять регулярно. Причина – если ошибка возникла,
то она вполне может появляться еще не один раз. При выходе каждой
новой версии программы желательно проверять, какие ошибки были
до этого, т. к. они могут появляться заново в дальнейшем.
Тестирование по тестовым случаям (конфигурационное и интеграционное) проводится по мере составления этих случаев по итера25
циям. Кроме того, оно может проводиться регрессионно, то есть по
мере исправления обнаруженных ошибок, добавления новой функциональности либо внесения изменений заказчика. На завершающем
этапе разработки проводится тестирование по всем составленным тестовым случаям.
Usability- и Exploratory-тестирование также проводится по итерациям, если есть уже макет, реализующий какую-либо функциональность продукта (для Exploratory), либо просто макет пользовательского интерфейса (для Usability). Оно также может проводиться регрессионно, по мере исправления обнаруженных ошибок, добавления новой функциональности либо внесения изменений заказчика. На завершающем этапе разработки проводится контрольное Usability- и
Exploratory-тестирование системы в целом.
Тестировать производительность продукта не всегда целесообразно, а также не всегда нужно проводить все тесты производительности (например, для одного продукта достаточно только нагрузочного
тестирования, для другого – как нагрузочного, так и объемного и
т. п.). Тестирование производительности должно проходить на как
можно более ранних этапах разработки, чтобы в случае неудовлетворительных результатов тестирования как можно раньше внести изменения
в архитектуру продукта. Кроме того, оно проводится после исправления
обнаруженных ошибок и на завершающем этапе разработки.
Unit-тестирование проводится на этапе разработки и только в
случаях, где срабатывают критерии необходимости использования
модульного тестирования (см. Лабораторную работу №6).
Приемочное тестирование проводится после того, как был реализован пользовательский интерфейс и/или добавлена новая функциональность. Также данный вид тестирования проводится на завершающем этапе проекта, перед сдачей продукта клиенту.
3.2. Конфигурация платформ
на которых проводится тестирование
Указывается, какие были выбраны конфигурации и почему.
3.3. Инструменты, с помощью которых
проводится тестирование
Для проведения тестирования по тестовым случаям используется
инструмент MicrosoftTestManager 2010 (рис 5.1).
26
Рис. 5.1. MicrosoftTestManager 2010
Для проведения тестирования производительности используется
среда разработки MicrosoftVisualStudio 2010 (рис. 5.2).
Рис. 5.2. Инструмент для определения производительности
Веб-приложений входящий в состав среды разработки
MicrosoftVisualStudio 2010 Ultimate
27
3.4. Тестовые случаи (TestCases)
TestCases составляются по«требованиям»заказчика (User Stories)
менеджером проекта в среде разработки MicrosoftVisualStudio 2010
либо в Microsoft Test Manager 2010.
При составлении тест – стратегии не нужно прописывать все
TestCases полностью, достаточно указать лишь название тестового
случая (либо название набора тестовых случаев), которое дает представление о тестируемой функциональности.
Пример тест-стратегии для программы «Алгоритм Rijndael»:
1. Виды тестирования.
В процессе тестирования будет проведено конфигурационное тестирование, usability-тестирование, exploratory-тестирование и приемочное тестирование.
2. Конфигурация платформ, на которых проводится тестирование.
Так как данный программный продукт является WinFormsприложением, то для конфигурационного тестирования достаточно
протестировать систему на одной-трех наиболее распространенных
операционных систем. Тестирование будет проводится на компьютере
с операционной системой WindowsХР.
3. Инструменты, с помощью которых проводится тестирование.
Так как тест – планом и тест – стратегией предусмотрено тестирование по тестовым случаям будет использоваться инструмент
MicrosoftTestManager 2010.
4. Тестовые случаи.
1. Запуск программы.
2. Шифрование данных.
3. Дешифрование данных.
4. Закрытие программы.
4. Отчетная документация
Отчетная документация формируется после завершения всех
предусмотренных видов тестирования.
В ходе тестирования могут быть обнаружены ошибки. Ошибки
могут быть двух видов – критические и некритические. Критические
ошибки существенно влияют на работоспособность продукта, некри28
тические ошибки представляют собой несущественные недоработки и
несущественно влияют на работоспособность продукта. Если в ходе
тестирования были обнаружены ошибки или проблемы, то человек,
проводивший тестирование, может предложить вариант исправления
ошибки или решения проблемы.
Пример отчета по тестированию для программы «Алгоритм
Rijndael»:
Usability-тестирование
В процессе работы с системой были оценены критерии удобства и
простоты пользования программой с точки зрения пользователя, имеющего средний уровень по работе с компьютером.
Система удобна и проста в использовании, пользователю среднего уровня владения компьютером не нужно обращаться к справочной
документации или специалисту. Логика работы системы проста и понятна. Возможность настройки системы под нужды пользователя
преднамеренно не была реализована, так как данная система обслуживает специализированную предметную область, где такая функциональность не нужна. Тем не менее, система получила высокую оценку
usability.
Для оценки usability системы использовались следующие критерии.
Таблица 5.1
Критерии оценки usability системы
Вопрос
Система способна делать все, что мне нужно
Система работает достаточно быстро
Мне нравится внешний вид интерфейса
Систему можно легко настроить под мои нужды
Начать работу было легко; я не столкнулся с существенными трудностями
Во время работы с системой я чувствовал себя вполне
уверенно
В любой момент времени я понимал, что должен сделать дальше
Система представляется мне полезной, я бы с удовольствием использовал бы её для решения моих задач
29
Ответ
(да/нет)
Да
Да
Да
Нет
Да
Да
Да
Да
Приемочное тестирование
Все TestCases были пройдены успешно, что говорит о полном соответствии тестируемой системы всем заявленным требованиям.
Конфигурационное тестирование
Для конфигурационного тестирования были записаны TestCase 1
– TestCase 4, проведенные на конфигурации с операционной системой
WindowsХР.
Все тесты прошли успешно. Ошибки не выявлены.
ExploratoryTesting
В процессе проведения Exploratory-тестирования были произведены произвольные действия с системой. Для данного тестирования
использовалась конфигурации с операционной системой Windows ХР.
В процессе Exploratory-тестирования ошибок выявлено не было.
Выводы
Таблица 5.2
Сводная информация по тестированию
Тип тестирования
Приемочное
Конфигурационное
Usability-тестирование
Exploratory
Ошибка
Количество
-
0
0
0
Уровень
ошибок
-
В целом тестирование прошло успешно. Пользователи высоко
оценили возможности программы и ее интерфейс.
Порядок работы
по созданию теста в MicrosoftTestManager 2010
1. Запускаем среду Microsoft Test Manager 2010.
2. Подключаемся к командному проекту.
3. Создаем новый план тестирования.
4. Создаем набор тестовых случаев.
5. Создаем тесты.
30
Практическая работа №6
СОЗДАНИЕ МОДУЛЬНЫХ ТЕСТОВ
ДЛЯ АВТОМАТИЗИРОВАННОГО ТЕСТИРОВАНИЯ
ИСХОДНОГО КОДА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ
Цель работы: ознакомиться с общими принципами разработки
модульных тестов в среде MicrosoftVisualStudio2010 с использованием
MSTest.
Модульное тестирование, или юнит-тестирование (англ.
unittesting) – вид тестирования при котором осуществляется проверка
корректности отдельных модулей программы. Под модулями понимается атомарная часть кода, не поддающаяся дальнейшему делению.
Это может быть функция, в некоторых случаях класс. Модульный тест
проверяет работоспособность модуля в условиях изоляции от других
модулей приложения. Исключив влияние других модулей, мы проверяем наш модуль в стерильных условиях: если результат выполнения
модульного теста не соответствует ожидаемому, то ошибка кроется в
логике нашего модуля, а не во внешних факторах. Идея состоит в том,
чтобы писать тесты для каждой нетривиальной функции или метода,
учитывая все возможные варианты исполнения. Это позволяет легко
тестировать базовые кирпичики приложения.
1. Аргументы в пользу модульных тестов
1. Улучшение качества кода. По сути, комбинация “основного”
кода и модульных тестов – это двойная запись одной и той же функциональности. В коде могут быть ошибки. В тесте могут быть ошибки. Но вероятность ошибки в коде и в тесте гораздо меньше.
2. Возможность проводить рефакторинг (улучшение структуры
кода) без опасений поломать работу приложения и погрязнуть в отладке. Основное назначение модульных тестов состоит не столько в
том, чтобы находить баги в текущей версии продукта, сколько в том,
чтобы не пропустить баги в старой функциональности при добавлении новой. К примеру, маленькое “улучшение” в алгоритме шифрования не разрушит всю систему, если на алгоритм и смежные компоненты есть модульные тесты.
3. Скорость нахождения ошибок. Ошибки будут найдены быстрее. Безусловно, написание тестов требует времени, особенно на этапе
31
овладения этим навыком. Но чем больше опыт, тем быстрее будет
движение вперед – не столько в написании тестов, сколько в развитии
всего продукта. Новая функциональность будет внедряться быстрее,
без досадных разбирательств о том, что могло привести к поломке
старого кода.
4. Более удобная координация работы распределенной группы
программистов. Модульные тесты позволяют провести приемочные
испытания перед интегрированием модулей в единую систему.
5. Модульные тесты служат дополнением к документации и помогают новому разработчику войти в курс дела. Объектноориентированные языки программирования предполагают наличие зависимостей между классами. Небольшое изменение в, казалось бы,
второстепенном классе, способно разрушить работу всей системы, поэтому модульные тесты в таких случаях могут оказаться очень полезны.
2. Аргументы против модульных тестов
1. Модульных тестов недостаточно для качественного тестирования приложений. Ясно, что модульные тесты не охватывают работу
всей системы в целом. Они проверяют систему с позиций разработчика и не могут взглянуть на приложение глазами пользователя. Модульные тесты, как правило, не охватывают полный набор входных
данных. Возможность увидеть все множество вариантов появляется
только при интеграционном тестировании всей системы.
2. Модульные тесты – это не панацея. Они покажут наличие
ошибок, но не докажут их отсутствие.
3. Рекомендации по созданию модульных тестов
1. Не надо тестировать каждый класс, каждый интерфейс. Только
самые значимые. Модульные тесты призваны проверять базовую
функциональность и наиболее критичные участки – наиболее “ценный” код. Модульные тесты – это инструмент, который должен себя
оправдывать. Необходимо найти разумную границу между отказом от
тестов и полным покрытием кода. К примеру, если найден баг, то
можно проанализировать, можно ли было его поймать модульными
тестами и учесть это в будущем.
2. Модульные тесты полезны для проверки сценариев, которые
трудно или дорого воспроизвести при тестировании через пользовательский интерфейс.
32
3. Особое внимание логике приложения (if, for, while и т. п.).
4. Нужно минимизировать время прогона модульных тестов. Они
должны выполняться быстро, иначе в них нет смысла. Поэтому каждый модульный тест должны быть достаточно “скоротечным”.
5. Модульный тест должен быть простым, охватывать 1-2 метода. Если зажегся красный свет, разработчику сразу должно быть ясно,
в чем причина возникшей проблемы.
6. В модульных тестах желательно обходиться без обращения к
базам данных, сокетам и прочим объектам “внешнего мира”, иначе
это будет не модульный, а интеграционный тест. Напомним, что тест
должен выполняться быстро, иначе в нем нет никакого смысла. Это
значит, что в модульном тесте не должно быть никакого вводавывода.
7. Модульные тесты – это основание пирамиды тестирования,
проверка базовой функциональность, отлов логических ошибок. В деле
обеспечения качества продукта они необходимы, но недостаточны. Над
ними располагаются функциональные тесты – к примеру, охватывающие взаимодействие с базами данных или объектами в Интернете. Затем следуют интеграционные тесты, проверяющие взаимодействие
компонентов системы. Далее идут приемочные тесты с позиции пользователя (воспроизвести базовые сценарии, по которым будет действовать пользователь системы). И наконец, исследовательское тестирование – вершина пирамиды и полновластная епархия тестировщика.
4. Разработка через тестирование
Разработка через тестирование (test-drivendevelopment, TDD) —
техника разработки программного обеспечения, которая основывается
на повторении очень коротких циклов разработки: сначала пишется
тест, покрывающий желаемое изменение, затем пишется код, который
позволит пройти тест и под конец проводится рефакторинг нового кода к соответствующим стандартам.
Тест – это процедура, которая позволяет либо подтвердить, либо
опровергнуть работоспособность кода. Когда программист проверяет
работоспособность разработанного им кода, он выполняет тестирование вручную. В данном контексте тест состоит из двух этапов: стимулирование кода и проверки результатов его работы. Автоматический
тест выполняется иначе: вместо программиста стимулированием кода
и проверкой результатов занимается компьютер, который отображает
на экране результат выполнения теста: код работоспособен или код
33
неработоспособен. Методика разработки через тестирование позволяет получить ответы на вопросы об организации автоматических тестов
и выработке определенных навыков тестирования.
TDD не только предполагает проверку корректности, но и влияет
на дизайн программы. Опираясь на тесты, разработчики могут быстрее представить, какая функциональность необходима пользователю.
Таким образом, детали интерфейса появляются задолго до окончательной реализации решения.
5. Добавление теста
При разработке через тестирование, добавление каждой новой
функциональности (feature) в программу, начинается с написания теста. Неизбежно этот тест не будет проходить, поскольку соответствующий код ещё не написан (Если же написанный тест прошёл, это
означает, что либо предложенная «новая» функциональность уже существует, либо тест имеет недостатки). Чтобы написать тест, разработчик должен чётко понимать предъявляемые к новой возможности
требования. Для этого рассматриваются возможные сценарии использования и пользовательские истории. Новые требования могут также
повлечь изменение существующих тестов. Это отличает разработку
через тестирование от техник, когда тесты пишутся после того, как
код уже написан: она заставляет разработчика сфокусироваться на
требованиях до написания кода — тонкое, но важное отличие.
6. Запуск всех тестов: убедиться, что новые тесты не проходят
На этом этапе проверяют только что написанные тесты на непроходимость. Этот этап также проверяет сами тесты: написанный тест
может проходить всегда и соответственно быть бесполезным. Новые
тесты должны не проходить по объяснимым причинам. Это увеличит
уверенность (хотя не будет гарантировать полностью), что тест действительно тестирует то, для чего он был разработан.
7. Написать код
На этом этапе пишется новый код так, что тест будет проходить.
Этот код не обязательно должен быть идеален. Допустимо, чтобы он
проходил тест каким-то неэлегантным способом. Это приемлемо, поскольку последующие этапы улучшат и отполируют его.
34
Важно писать код, предназначенный именно для прохождения теста.
Не следует добавлять лишней и, соответственно, не тестируемой
функциональности.
8. Запуск всех тестов: убедиться, что все тесты проходят
Если все тесты проходят, программист может быть уверен, что
код удовлетворяет всем тестируемым требованиям. После этого можно приступить к заключительному этапу цикла.
9. Рефакторинг
Когда достигнута требуемая функциональность, на этом этапе код
может быть почищен. Рефакторинг – процесс изменения внутренней
структуры программы, не затрагивающий ее внешнего поведения и
имеющий целью облегчить понимание ее работы, устранить дублирование кода, облегчить внесение изменений в ближайшем будущем.
10. Повторить цикл
Описанный цикл повторяется, реализуя всё новую и новую функциональность. Шаги следует делать небольшими, от 1 до 10 изменений между запусками тестов. Если новый код не удовлетворяет новым
тестам или старые тесты перестают проходить, программист должен
вернуться к отладке. При использовании сторонних библиотек не следует делать настолько небольшие изменения, которые буквально тестируют саму стороннюю библиотеку, а не код, её использующий,
если только нет подозрений, что библиотека содержит ошибки.
11. Преимущества
Несмотря на то, что при разработке через тестирование требуется
написать большее количество кода, общее время, затраченное на разработку, обычно оказывается меньше. Тесты защищают от ошибок.
Поэтому время, затрачиваемое на отладку, снижается многократно.
Большое количество тестов помогает уменьшить количество ошибок в
коде. Устранение дефектов на более раннем этапе разработки препятствует появлению хронических и дорогостоящих ошибок, приводящих к длительной и утомительной отладке в дальнейшем.
35
12. Недостатки
Самым первым недостатком данного подхода является то, что к
нему сложно привыкнуть ментально.
Разработку через тестирование сложно применять в тех случаях, когда для тестирования необходимо прохождение функциональных тестов.
Примерами может быть: разработка интерфейсов пользователя, программ, работающих с базами данных, а также того, что зависит от специфической конфигурации сети. Разработка через тестирование не предполагает большого объема работы по тестированию такого рода вещей. Она
сосредотачивается на тестировании отдельно взятых модулей.
Модульные тесты, создаваемые при разработке через тестирование, обычно пишутся теми же, кто пишет тестируемый код. Если разработчик неправильно истолкует требования к приложению, и тест, и
тестируемый модуль будут содержать ошибку.
Большое количество используемых тестов могут создать ложное
ощущение надежности, приводящее к меньшему количеству действий
по контролю качества.
13. Рекомендации по созданию модульных тестов
1. Не надо тестировать каждый класс, каждый интерфейс. Только
самые значимые. Модульные тесты призваны проверять базовую
функциональность и наиболее критичные участки – наиболее “ценный” код. Модульные тесты – это инструмент, который должен себя
оправдывать. Необходимо найти разумную границу между отказом от
тестов и полным покрытием кода. К примеру, если найден «баг», то
можно проанализировать, можно ли было его поймать модульными
тестами и учесть это в будущем.
2. Модульные тесты полезны для проверки сценариев, которые
трудно или дорого воспроизвести при тестировании через пользовательский интерфейс.
3. Особое внимание необходимо уделять логике приложения (if,
for, while и т. п.).
4. Нужно минимизировать время «прогона» модульных тестов.
Они должны выполняться быстро, иначе в них нет смысла. Поэтому
каждый модульный тест должны быть достаточно “скоротечным”.
5. Модульный тест должен быть простым, охватывать 1-2 метода. Если зажегся красный свет, разработчику сразу должно быть ясно,
где собака зарыта.
36
6. В модульных тестах желательно обходиться без обращения к базам данных, сокетам и прочим объектам “внешнего мира”, иначе это будет
не модульный, а интеграционный тест. Напомним, что тест должен выполняться быстро, иначе в нем нет никакого смысла. Это значит, что в модульном тесте не должно быть никакого ввода-вывода.
7. Модульные тесты – это основание пирамиды тестирования,
проверка базовой функциональность, отлов логических ошибок. В деле
обеспечения качества продукта они необходимы, но недостаточны. Над
ними располагаются функциональные тесты – к примеру, охватывающие взаимодействие с базами данных или объектами в Интернете. Затем следуют интеграционные тесты, проверяющие взаимодействие
компонентов системы. Далее идут приемочные тесты с позиции пользователя (воспроизвести базовые сценарии, по которым будет действовать пользователь системы). И наконец, исследовательское тестирование – вершина пирамиды и полновластная епархия тестировщика.
Следующий этап – закрепление материала на практике. Создадим
новое консольное приложение “QuadraticEquation”, позволяющее решать
квадратные уравнения (рис. 6.1.). Разработку будем вести в соответствии
с принципами TDD, тестирование производить с помощью MSTest.
Рис. 6.1. Создание проекта
37
Добавим новый класс “QuadraticEquation”, который и будет содержать всю логику приложения. Для этого в окне “Обозреватель решений” выделим проект “QuadraticEquation” и вызовем контекстное
меню, нажав правую кнопку мыши. Выберем пункт “Добавить”, и в
подменю кликнем по элементу “Класс”. В качестве названия укажем
“QuadraticEquation”.
Приведем исходный код вновь созданного класса в соответствие с
листингом6.1. Генерация исключения NotImplementedException нужна
для того, что бы обозначить еще не реализованную функциональность.
Листинг 6.1
Public Class QuadraticEquation
Private _A As Integer
Private _B As Integer
Private _C As Integer
Public Property A() As Integer
Get
Throw New NotImplementedException()
End Get
Set(ByVal value As Integer)
Throw New NotImplementedException()
End Set
End Property
Public Property B() As Integer
Get
Throw New NotImplementedException()
End Get
Set(ByVal value As Integer)
Throw New NotImplementedException()
End Set
End Property
Public Property C() As Integer
Get
Throw New NotImplementedException()
End Get
Set(ByVal value As Integer)
Throw New NotImplementedException()
End Set
End Property
38
Public Sub New(ByVal a As Integer, _
ByVal b As Integer, ByVal c As Integer)
Throw New NotImplementedException()
End Sub
End Class
Теперь сформируем тесты для нашего класса. VisualStudio помогает в этой задаче, генерирую часть кода автоматически. Кликнем
правой кнопкой мыши по конструктору, и в контекстном меню выберем пункт “Создать модульные тесты…” (рис. 6.2).
Рис. 6.2. Создание модульных тестов
В появившемся окне (рис. 6.3) отмечены члены классов, для которых будут сформированы заготовки тестов. Вносить изменения нет
нужды.
Так как мы создаем первый тест, VisualStudio запросит название
для нового проекта, который будет содержать тесты. Введем “Test”.
Наш тест будет предназначен для проверки того, что значения параметров a, b и c конструктора нашего класса будут сохранены в одноименных свойствах. Для этого приведем код теста в соответствие с
листингом 6.2.
39
Рис. 6.3. Окно «Создать модульные тесты»
Листинг 6.2
'''<summary>
'''ТестдляКонструкторQuadraticEquation
'''</summary>
<TestMethod()> _
Public Sub QuadraticEquationConstructorTest()
Dim a As Integer = 1
Dim b As Integer = 2
Dim c As Integer = 3
Dim
equation
As
QuadraticEquation.QuadraticEquation_
= New QuadraticEquation.QuadraticEquation(a, b,
c)
Assert.AreEqual(equation.A, a)
Assert.AreEqual(equation.B, b)
Assert.AreEqual(equation.C, c)
EndSub
40
Теперь выполним наш, пока единственный, тест. Для этого выберем пункт меню “Тест”. Раскроем подменю “Окна” и кликнем по
пункту “Представление теста” (рис. 6.4).
Рис. 6.4. Открытие окна “Представление теста”
В появившемся окне кликнем правой кнопкой мыши по нашему тесту
и в появившемся меню выберем “Выполнить выбранное” (рис. 6.5).
Рис. 6.5. Выполнение теста
41
Наш тест провален, что полностью согласуется со схемой TDD
(рис. 6.6).
Рис. 6.6. Результаты теста
Для того чтобы реализовать тестируемую функциональность, приведем код класса “QuadraticEquation ” в соответствие с листингом 6.3.
Листинг 6.3
Public Class QuadraticEquation
Private _A As Integer
Private _B As Integer
Private _C As Integer
Public Property A() As Integer
Get
Return _A
End Get
Set(ByVal value As Integer)
_A = value
End Set
End Property
Public Property B() As Integer
Get
Return _B
End Get
Set(ByVal value As Integer)
_B = value
End Set
End Property
Public Property C() As Integer
Get
Return _C
End Get
Set(ByVal value As Integer)
_C = value
End Set
42
End Property
Public Sub New(ByVal a As Integer, _
ByVal b As Integer, ByVal c As Integer)
Me.A = a
Me.B = b
Me.C = c
EndSub
EndClass
И вновь запустим наш тест. Теперь он завершился успешно (рис. 6.7.).
Рис. 6.7. Результаты теста
Теперь необходимо запретить устанавливать значение свойства A
равным «0». Сначала напишем тест. Кликнем правой кнопкой мыши
по свойству A. В меню выберем пункт “Создать модульные тесты…”
(рис. 6.8).
Рис. 6.8. Создание теста
43
Приведем исходный код вновь созданного теста в соответствие с
листингом 6.4.
Листинг 6.4
'''<summary>
'''ТестдляA
'''</summary>
<TestMethod()> _
<ExpectedException(GetType(ArgumentException))> _
Public Sub ATest()
Dim a As Integer = 1
Dim b As Integer = 2
Dim c As Integer = 3
Dim equation As QuadraticEquation.QuadraticEquation_
= New QuadraticEquation.QuadraticEquation(a, b, c)
equation.A = 0
EndSub
В окне “Представление теста”, выделим оба теста, кликнем правой кнопкой мыши, и в появившемся меню выберем пункт “Выполнить выбранное” (рис. 6.9).
Рис. 6.9. Выполнение тестов
44
В результате наш первый тест завершился успешно, а второй закончился неудачей (рис. 6.10).
Рис. 6.10. Результат тестов
Чтобы реализовать данную функциональность – изменим код
свойства A согласно листингу 6.5.
Листинг 6.5
Public Property A() As Integer
Get
Return _A
End Get
Set(ByVal value As Integer)
If value = 0 Then
Throw New ArgumentException(_
"ЗначениеAнеможетравняться 0.")
End If
_A = value
End Set
End Property
Перезапустим оба теста. Теперь они оба выполнились успешно
(рис. 6.11).
Рис. 6.11. Выполнение тестов
Задание на лабораторную работу
Реализовать функции вычисления дискриминанта и корней уравнения.
45
Литература
1. Кларк Д. Объектно-ориентированное программирование в
VisualBasic .NET. СПб.: Питер, 2003.
2. Ник Рендольф, Дэвид Гарднер, Майкл Минутилло, Крис АндерсонVisual Studio 2010 для профессионалов. М.: Диалектика, 2011.
3. Кровчик Э., Кумар В., Лагари Н., Мунгале А., Нагел К., Паркер
Т., Шивакумар Ш. .NET Сетевое программирование для профессионалов. М.: Лори, 2004.
4. Блэк У. Интернет: протоколы безопасности. СПб.: Питер, 2001.
5. ГОСТ Р 34.10-2001. Информационная технология. Криптографическая защита информации. Процедуры выработки и проверки
электронной цифровой подписи на базе асимметричного криптографического алгоритма.
6. Саломаа А. Криптография с открытым ключом: Пер. с англ.
М.: Мир, 1996.
46
Download