Файл: отладка и тестирвание программ.pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 28.03.2023

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

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Листинг 1

1

public void Parse()

2

{

3

using (FileStream stream = new FileStream(_filePath, FileMode.Open, FileAccess.Read))

1

4

{

5

StreamReader reader = new StreamReader(stream);

2

6

while (!reader.EndOfStream)

3

7

{

8

string line = reader.ReadLine().ToLower();

4

9

int openBracket;

10

string initialForm = "";

11

try

12

{

13

openBracket = line.IndexOf('(');

5

14

if (openBracket == -1)

6

15

throw new DictionaryException(_dictionaryType,

7

16

DictionaryExceptionReason. НевозможноПроанализироватьВариантыФорм);

17

initialForm = string.Concat(line .Where((c, i) => i < openBracket)).Trim().ToUpper();

8

18

}

19

catch

9

20

{

21

throw new DictionaryException(_dictionaryType,

22

DictionaryExceptionReason. НеОбнаруженаНачальнаяФорма);

23

}

24

Dictionary[initialForm] = new List<string>() {initialForm};

10

25

Dictionary[initialForm].AddRange(line.Substring(openBracket + 1)

26

.Split(new string[] {",", ")"},

27

StringSplitOptions. RemoveEmptyEntries)

28

.Select(s => s.Trim().ToUpper())

29

.ToList());

30

}

11

31

reader.Close();

12

32

}

13

33

}

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

Подготовка тестовых вариантов

Для тестирования каждого из независимых путей были созданы тестовые варианты исходных данных. Сами данные (ИД), ожидаемый от них результат (ОЖ. РЕЗ.) и результат, полученный фактически при выполнении программы (Ф. РЕЗ.), приведены в Таблица 5. Тестирование выполняется для справочника «Субъекты».

Таблица 5. Тестовые варианты для метода базового пути

ИД

ОЖ. РЕЗ.

1

Файл Субъекты.txt отсутствует

Выброшено исключение FileNotFoundException, которое затем перехвачено в методе Program.Main.

2

Файл Субъекты.txt не содержит данных

Свойство DictionaryParser.Dictionary инициализировано пустым словарем.

3

Файл Субъекты.txt содержит одну или несколько корректных строк:

Студент (Студента, Студенту, Студентом, Студенте)

Студенты (Студентов, Студентам, Студентами, Студентах)

Свойство DictionaryParser.Dictionary содержит словарь:

СТУДЕНТ ->

[0]: "СТУДЕНТ"

[1]: "СТУДЕНТА"

[2]: "СТУДЕНТУ"

[3]: "СТУДЕНТОМ"

[4]: "СТУДЕНТЕ"

СТУДЕНТЫ ->

[0]: "СТУДЕНТЫ"

[1]: "СТУДЕНТОВ"

[2]: "СТУДЕНТАМ"

[3]: "СТУДЕНТАМИ"

[4]: "СТУДЕНТАХ"

4

Файл Субъекты.txt содержит одну или несколько некорректных строк:

Студент Студента, Студенту, Студентом, Студенте)

Примечание: отсутствует символ ‘(‘

Выброшено исключение DictionaryException, которое затем перехвачено в методе Program.Main.


Тестирование ветвей и операторов отношений.

В рассматриваемом модуле есть три условных оператора, условия для которых записаны операторами 1, 3, 6. Метод ветвей и операторов отношений будем выполнять только в последнем случае, так как первый реализован средствами .NET Framework, а второй задает условие цикла и будет протестирован позднее:

if (openBracket == -1)

throw new DictionaryException(_dictionaryType,

DictionaryExceptionReason.НевозможноПроанализироватьВариантыФорм);

В этом случае, очевидно, достаточно рассмотреть два случая:

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

Тестирование потоков данных.

Определим DU-цепочки и представим их в виде списка цепочек.

Получены следующие цепочки:

        1. [line, 4, 8]
        2. [line, 4, 10]
        3. [openBracket, 5, 6]
        4. [openBracket, 5, 10]
        5. [initialForm, 8, 10]

Исходя из полученного списка цепочек, необходимо проанализировать поведение трех переменных (локальных переменных метод). Так как значения переменной openBracket зависит от line, а значения initialForm – от line и openBracket, то достаточно рассмотреть все требуемые варианты переменной line:

        1. null
        2. “”
        3. Студент (Студента, Студенту, Студентом, Студенте)
        4. Студент Студента Студенту Студентом Студенте

Тестирование циклов.

В модуле представлен единственный цикл типа «ПОКА <условие> ВЫПОЛНЯТЬ <действие>».

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

        1. Единственная строка в файле
        2. Две строки в файле
        3. Более двух строк в файле.

Корректность записанных строк не принципиальна, так как условие некорректной записи было протестировано выше.

Набор модульных тестов.

Каждый тест сопровождается XML-комментарием, который описывает ситуацию и требуемое поведение программы.

#region Parser itself

/// <summary>

/// Проверяет случай отсутствия файла со справочником: все исключения перехвачены

/// </summary>

[Test]

public static void Dictionary_FileNotFound_ExceptionCaught()

{

File.Move("Data/Субъект.txt", "Data/Субъект1.txt");


Assert.Throws<DictionaryException>(() => new DictionaryParser(DictionaryType.Субъект));

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай пустого файла: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_EmptyFile_NoExceptions()

{

File.Move("Data/Субъект.txt", "Data/Субъект1.txt");

File.Delete("Data/Субъект.txt");

var writer = File.CreateText("Data/Субъект.txt");

writer.Close();

DictionaryParser parser = null;

Assert.DoesNotThrow(() => parser = new DictionaryParser(DictionaryType.Субъект));

Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();

CollectionAssert.AreEquivalent(parser.Dictionary, dictionary);

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай любого числа корректных строк в файле: корректное заверешение работы

/// </summary>

[Test]

public static void Dictionary_AllLinesParsedSuccessfully_NoExceptions()

{

CreateFake();

DictionaryParser parser = null;

Assert.DoesNotThrow(() => parser = new DictionaryParser(DictionaryType.Субъект));

Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();

dictionary["СТУДЕНТ"] = new List<string>() {"СТУДЕНТ", "СТУДЕНТА", "СТУДЕНТУ", "СТУДЕНТОМ", "СТУДЕНТЕ"};

dictionary["СТУДЕНТЫ"] = new List<string>()

{"СТУДЕНТЫ", "СТУДЕНТОВ", "СТУДЕНТАМ", "СТУДЕНТАМИ", "СТУДЕНТАХ"};

foreach (var key in dictionary.Keys)

{

CollectionAssert.AreEquivalent(parser.Dictionary[key].OrderBy(x => x),

dictionary[key].OrderBy(x => x));

}

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай некорректной записи строки в файле: все исключения перехвачены

/// </summary>

[Test]

public static void Dictionary_InvalidRecord_ExceptionCaught()

{

File.Move("Data/Субъект.txt", "Data/Субъект1.txt");

File.Delete("Data/Субъект.txt");

var writer = File.CreateText("Data/Субъект.txt");

writer.WriteLine("Студент Студента, Студенту, Студентом, Студенте)");

writer.Close();

DictionaryParser parser = null;

Assert.Throws<DictionaryException>(() => parser = new DictionaryParser(DictionaryType.Субъект));

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

#endregion

#region Containing

/// <summary>

/// Проверяет случай наличия формы слова в словаре: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_ContainsSpecificForm_NoExceptions()

{

CreateFake();

DictionaryParser parser = new DictionaryParser(DictionaryType.Субъект);

Assert.AreEqual(true, parser.Contains("студентов"));

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай отсутствия формы слова в словаре: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_DoesNotContainSpecificForm_ExceptionCaught()

{

CreateFake();

DictionaryParser parser = new DictionaryParser(DictionaryType.Субъект);

Assert.AreEqual(false, parser.Contains("стьюдентс"));

File.Delete("Data/Субъект.txt");


File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

#endregion

#region Initial form

/// <summary>

/// Проверяет случай наличия начальной формы слова в словаре: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_InitialFormRevealed_NoExceptions()

{

CreateFake();

DictionaryParser parser = new DictionaryParser(DictionaryType.Субъект);

Assert.AreEqual("студенты".ToUpper(), parser.GetInitialForm("студентов"));

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай отсутствия начальной формы слова в словаре: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_InitialFormDidNotReveal_ExceptionCaught()

{

CreateFake();

DictionaryParser parser = new DictionaryParser(DictionaryType.Субъект);

Assert.AreEqual("стьюдентов", parser.GetInitialForm("стьюдентов"));

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

/// <summary>

/// Проверяет случай отсутствия начальной формы слова в пустом файле: корректное завершение работы

/// </summary>

[Test]

public static void Dictionary_InitialFormDidNotRevealFromEmptyFile_ExceptionCaught()

{

File.Move("Data/Субъект.txt", "Data/Субъект1.txt");

File.Delete("Data/Субъект.txt");

var writer = File.CreateText("Data/Субъект.txt");

writer.Close();

DictionaryParser parser = new DictionaryParser(DictionaryType.Субъект);

Assert.AreEqual("стьюдентов", parser.GetInitialForm("стьюдентов"));

File.Delete("Data/Субъект.txt");

File.Move("Data/Субъект1.txt", "Data/Субъект.txt");

}

#endregion

/// <summary>

/// Вспомогательный метод для подготовки стандартных файлов

/// </summary>

private static void CreateFake()

{

File.Move("Data/Субъект.txt", "Data/Субъект1.txt");

File.Delete("Data/Субъект.txt");

var writer = File.CreateText("Data/Субъект.txt");

writer.WriteLine("Студент (Студента, Студенту, Студентом, Студенте)");

writer.WriteLine("Студенты (Студентов, Студентам, Студентами, Студентах)");

writer.Close();

}

Модуль String.Capitalize()

Алгоритм и код

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

Листинг 2

1

public static string Capitalize(this string s)

2

{

3

if (String.IsNullOrEmpty(s))

1

4

return "";

2

5

6

string res = "";

3

7

res += s[0];

8

9

for (int i = 1; i < s.Length; i++)

4

10

{

11

res += (_delimeters.Contains(s[i - 1])

5

12

? Char.ToUpper(s[i])

6

13

: s[i]);

7

14

}

8

15

res = res.Remove(" ");

9

16

16

return res;

10

16

}

11


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

Например, строка «Это строка из НЕСКОЛЬКИХ слов» будет преобразована к виду «ЭтоСтрокаИзНесколькихСтрок».

Данный метод является методом расширения для стандартного класса String из .NET Framework. Он используется в качестве вспомогательного для работы с перечислением Quntifier (Квантор) – см. полный программный код в Приложении (или электронном приложении к отчету).

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

Подготовка тестовых вариантов

Для тестирования каждого из независимых путей были созданы тестовые варианты исходных данных. Сами данные (ИД), ожидаемый от них результат (ОЖ. РЕЗ.) и результат, полученный фактически при выполнении программы (Ф. РЕЗ.), приведены в Таблица 6.

Таблица 6. Тестовые варианты для метода базового пути

ИД

ОЖ. РЕЗ.

1

null

Пустая строка

2

Пустая строка

Пустая строка

3

Это другая строка

ЭтоДругаяСтрока

4

Это Еще Одна Строка

ЭтоЕщеОднаСтрока

Тестирование ветвей и операторов отношений.

В рассматриваемом модуле есть три условных оператора, условия для которых записаны операторами 1, 4 (условие выхода из цикла) и 5 (в формате тернарного оператора – логической операции). Выполним тестирование для последнего оператора:

res += (_delimeters.Contains(s[i - 1])

? Char.ToUpper(s[i]) : s[i]);

В этом случае, очевидно, достаточно рассмотреть два случая (для некоторого индекса символа в строке i):

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

Достаточными будут следующие тест со строкой, в которой присутствуют как символы-разделители, так и буквенно-числовые символы.

Тестирование потоков данных.

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

Тестирование циклов.

В модуле представлен единственный цикл типа «ДЛЯ КАЖДОГО <переменная_итерации> ВЫПОЛНЯТЬ <действие>».