#c# #xml #unit-testing
#c# #xml #модульное тестирование
Вопрос:
У меня есть класс, который использует классы XmlReader и XmlReaderSettings в C # для проверки Xml-файлов на соответствие схеме. Поскольку мое приложение включает чтение XML-данных из базы данных, я решаю показать ошибку пользователю в окне сообщения. Таким образом, любые ошибки проверки, а также любые возникшие исключения будут отображаться со строкой «Произошла ошибка при синтаксическом анализе», появляющейся в окне сообщения.
У меня также есть логическая переменная, которая возвращает, был ли синтаксический анализ успешным или нет.
Прямо сейчас я использую логическое значение, возвращаемое функцией Parse в Assert, в то время как функция parse анализирует как допустимые, так и недействительные Xml-файлы.
Таким образом, во время выполнения набора тестовых примеров у меня есть эта стопка окон сообщений, скопившихся в другом окне.
Реальный вопрос, который у меня возник, заключался в том, нормально ли, что несколько таких окон сообщений появляются, в то время как платформа модульного тестирования в Visual Studio сообщает нам, все тесты пройдены или нет.
Или это тот случай, когда мне просто нужно вернуть значение bool, а затем класс GUI отображает соответствующее сообщение об ошибке.
Q2. Также, скажем, если мне действительно нужно проверить, правильно ли была проанализирована конкретная строка и сохранена в массив, могу ли я создать подкласс основного класса, чтобы добавить некоторую функциональность, которая могла бы помочь мне лучше писать модульные тесты?
Я был бы очень признателен за некоторые предложения относительно того, каким должен быть мой дизайн и модульное тестирование.
Кроме того, я признаю, что совершаю большую ошибку при написании модульных тестов после того, как я записал класс, который мне нужно протестировать, и я знаю, что должно быть наоборот.
Ответ №1:
Разбор Xml и отображение сообщений об ошибках — это отдельные задачи, поэтому ваш анализатор не должен иметь никаких знаний о том, как отображаются сообщения об ошибках.
В зависимости от ваших потребностей, есть несколько вариантов:
Исключения
Я часто живу по правилу: «Если метод не может выполнить свою работу, выдайте исключение». Если вам нужно остановиться при первой ошибке, можно использовать исключения.
С точки зрения модульного тестирования, если вы передаете недопустимые данные, убедитесь, что код выдает исключение, используя атрибут [ExpectedException].
[TestMethod, ExpectedException(typeof(ParserValidationException))]
public void IllegalDataShouldThrowValidationErrors()
{
var parser = new MyParser();
parser.Parse( dataThatContainsErrors );
}
Однако, если вам нужно игнорировать недопустимые данные и сообщать об ошибках, вам может потребоваться другой подход.
Специализированный возвращаемый тип
Если вам нужно собрать все ошибки, лучше всего сохранить проанализированный результат и ошибки вместе как объект.
public class ParsedResult<T>
{
public T Resu<
public List<string> Warnings;
}
С точки зрения модульного тестирования, вы должны убедиться, что список предупреждений не пуст, если вы передаете недопустимые данные.
[TestMethod]
public void ParsedResultsForIllegalDataShouldContainWarnings()
{
var parsedResult = new MyParser.Parse<Foo>( dataThatContainsErrors );
Assert.IsNotNull(parsedResult);
Assert.IsNotNull(parsedResult.Result);
Assert.AreEqual(1, parsedResult.Warnings.Count);
}
Отчет об ошибках
Передайте collaborator в объект и попросите его сообщить о своих результатах.
public ObjectToReturn Parse(string xml, IProgressReporter progress)
{
// create xml reader
// read values from xml
// if a value is invalid, log it
progress.AddMessage( "property x was invalid. ")
}
Отчет о ходе выполнения может быть оболочкой вокруг вашего MessageBox, или это может быть консольный вывод, регистратор и т.д. С точки зрения модульного тестирования, вы можете либо создать тестовый дубль, который фиксирует сообщения, либо вы можете использовать макет фреймворка и убедиться, что он вызывался определенное количество раз. Вот пример, в котором используется Moq.
var mockReporter = new Mock<IProgressReporter>();
IProgressReporter reporter = mockReporter.Object;
var parser = new MyParser();
var illegalData = // your illegal data;
var result = parser.Parse( illegalData, parser);
Assert.IsNotNull(result, "The value was not parsed correctly.");
mockReporter.Verify( r => r.AddMessage( It.IsAny<string>() ), Times.AtLeast(1));
Ответ №2:
Я думаю, вам не следует использовать MessageBox для сообщения об ошибках, а вместо этого передавать ошибки как List<string>
и отображать их в графическом интерфейсе.
Мне нравится разработка, основанная на тестировании, но написание тестов после написания реализации тоже работает. Для меня их написание требует больше усилий.