Юнит тесты для "системного" приложения
И как, ответ-то уже есть?
В смысле? На какой вопрос?
Не понимаю.
Ну вот кусок кода для настройки. Вроде всё верно. А гад реагирует на копирование каталога.
_watcher.Path = directoryName;
// Watch files only.
_watcher.IncludeSubdirectories = false;
// Watch all files.
_watcher.Filter = "*.*";
_watcher.Created += Watcher_Created;
//Start monitoring.
_watcher.EnableRaisingEvents = true;
Можно использовать какой-нибудь контейнер. Например Ninject.
никогда в моем коде не будет DI Container. И фиг поймешь как работает система, когда оно везде. И непонятно как отлаживать. Был уже такой проект.
Но есть и другие способы.
и какие интересно?
В любом случае нужно писать два класса, один тестовый и один реальный. Для одного случая еще как то можно и то неизвестно.
Вот например, в заглушке фиг бы додумался сразу - файл нужно вначале загнать в зип и при создании зип файла будет "ложное" извещение о копировании файла в каталог.
На какой вопрос?
Что ты хочешь тестировать?
Ну вот кусок кода для настройки. Вроде всё верно. А гад реагирует на копирование каталога.
_watcher.Path = directoryName;
// Watch files only.
_watcher.IncludeSubdirectories = false;
// Watch all files.
_watcher.Filter = "*.*";
_watcher.Created += Watcher_Created;
//Start monitoring.
_watcher.EnableRaisingEvents = true;
Это мило, то тут ты конфигурируешь некий объект _watcher. Никакой логики тут нет. Цикломатическая сложность этого кода равна 1.
Но предположим, что ты хочешь получить ошибку (исключение) в момент, когда выполныешь строку _watcher.EnableRaisingEvents = true; если directoryName - директория. И не получать исключение, если directoryName - файл.
В таком случае у тебя есть такой код:
public interface ISystemFile { System.IO.FileAttributes GetAttributes(string path); } public class SystemFile : ISystemFile { public FileAttributes GetAttributes(string path) { return System.IO.File.GetAttributes(path); } } public class FileSystemWatcher { ISystemFile _systemFiles = null; public FileSystemWatcher() : this (new SystemFile()) { } public FileSystemWatcher(ISystemFile systemFiles) { _systemFiles = systemFiles; } public string Path { get; set; } public bool IncludeSubdirectories { get; set; } public string Filter { get; set; } public event EventHandler Created; private bool _enableRaisingEvents = false; public bool EnableRaisingEvents { get { return _enableRaisingEvents; } set { if (value == true) { System.IO.FileAttributes att = _systemFiles.GetAttributes(Path); if (att == System.IO.FileAttributes.Directory) throw new Exception("blah-blah-blah"); } _enableRaisingEvents = value; } } }
Ну и тестируешь то, что надо:
[TestMethod] public void EnableRaisingEvents_TrueForFile_OK() { // Arrenge ISystemFile systemFile = Substitute.For<ISystemFile>(); systemFile.GetAttributes(Arg.Any<string>()).Returns(FileAttributes.Normal); FileSystemWatcher watcher = new FileSystemWatcher(systemFile); // Act watcher.EnableRaisingEvents = true; // Assert Assert.IsTrue (watcher.EnableRaisingEvents); } [TestMethod] [ExpectedException(typeof(Exception))] public void EnableRaisingEvents_TrueForDirectory_Exception() { // Arrenge ISystemFile systemFile = Substitute.For<ISystemFile>(); systemFile.GetAttributes(Arg.Any<string>()).Returns(FileAttributes.Directory); FileSystemWatcher watcher = new FileSystemWatcher(systemFile); // Act watcher.EnableRaisingEvents = true; // Assert }
и какие интересно?
Ну например тоже сделать виртуальную функцию, которая будет возвращать реальную обертку. В тесте такую функцию можно перегрузить.
reentrancy
Попробуй на примере сформулировать, что конкретно ты хочешь протестировать, увеличив количество файлов? То, что ты тестируешь - это ТВОЙ код или ты пытаешься посмотреть, как работает сторонняя библиотека? Именно твой код меняет поведение от количества файлов?
Могу логов нафигачить если не веришь, хоть и не проверял еще
Не надо. Опиши словами. Что должно произойти от увеличения количества файлов? Если ты используешь слова "быстрее", то это производительность.
и что тут тестировать
Только выzов самой функции. Вызывается и сколько раз вызывается. Это не твой код. Тут нечего тестировать.
На какой вопрос? Что ты хочешь тестировать?
Вообще то не вижу ничего, что имеет смысл покрывать юнит тестами.
Можно только создать сферического коня в вакууме и его тестировать
Это мило, то тут ты конфигурируешь некий объект _watcher. Никакой логики тут нет
Естественно, но именно так и не работает
Нужно было добавить еще одну строку
_watcher.NotifyFilter = NotifyFilters.FileName;
А что ты там тестируешь я так и не понял, для меня это какое то извращение, тем более что я пользую NUnit
Это не каталог. Это строка. В принципе путь к файлу, но вообще строка.
ну так в том то и дело. Не имеет значения, что я кидаю файл или каталог на выходе одна и таже строка.
И там еще буфер в 4К по умолчанию. Так что неизвестно будет ли работать для 1000 файлов и больше.
Если ты используешь слова "быстрее", то это производительность.
В данном случае от скорости меняется логика.
Я начинаю вызывать функцию по новому, когда она еще не закончила свою работу.
Кроме того как в "эмуляторе" отследить что эта функция создала новый файл к каталоге для мониторинга
Только выzов самой функции. Вызывается и сколько раз вызывается.
А на кой мне эвент тестировать? Сколько раз его вызвал столько и придет, вроде как системная функция.
Вообще то не вижу ничего, что имеет смысл покрывать юнит тестами.Можно. А можно задуматься о том, где могут быть проблемы в твоем коде и как смоделировать эти проблемы.
Можно только создать сферического коня в вакууме и его тестировать
Короче говоря можно попробовать ответить на следующие вопросы:
1) что является твоим Unit under test?
2) какие требования предъявляются к твоему Unit under test?
3) с какими объектами взаимодействуешь твой Unit under test?
Ну и после того, как это все станет понятно, можно будет приступать к самим тестам.
Естественно, но именно так и не работает
ОК, что именно не работает в приведенном тобой коде?
А что ты там тестируешь я так и не понял
Тестируется setter проперти EnableRaisingEvents.
тем более что я пользую NUnit
Какая разница, в какой среде ты это тестируешь? NSubstitute - это библиотека для mock.
Не имеет значения, что я кидаю файл или каталог
Во первых ты не можешь кинуть файл. Кинуть можно обьект класса или базисный тип как параметр. Мы же внутри программного кода. Файл - это понятие файловой системы. В коде файловой системы нет, есть обьекты определенных классов с определенными параметрами. Вот это и тестируем
И там еще буфер в 4К по умолчанию.
где там? как твой код взаимодействует прямо или косвенно с буфером, что может произойти, какой ответ ты можешь получить?
А на кой мне эвент тестировать? Сколько раз его вызвал столько и придет, вроде как системная функция.
Не в этом дело. При определенных обстоятельствах в твоем коде может не дойти до вызова этой функции. Юниттест проверяет эти условия. Шаловливый коллега мог закоментировать вызов или заменить функцию другой. Юниттест защищает от этого. Но Юниттест не может дать результат "на этом компе результаты неудовлетворительные, компьютер медленный". В смысле может конечно, написать можно что угодно, но это будет неправильно. Юниттесты не снимают метрики.
Тестируется setter проперти EnableRaisingEvents.
А причем тогда файловая система?
System.IO.File.GetAttributes(path);
где могут быть проблемы в твоем коде и как смоделировать эти проблемы
А зачем их моделировать?
Сделаю я лучше пару временных тест каталогов и всё протестирую "наживую"
ОК, что именно не работает в приведенном тобой коде?
В приведенной версии, если я перемещаю каталог в директорию которая мониторится, возникает событие о создании объекта.
Мы же внутри программного кода
Не мы а Вы
Я говорил о реальном тесте, который мне нужен.
где там?
В FileSystemWatcher
A 4 KB buffer can track changes on approximately 80 files in a directory. Each event takes up 16 bytes in the buffer, plus enough bytes to store the name of the file, in Unicode (2 bytes per character), that the event occurred on.
Если дофига файлов накидаю, могу ничего и не получить. Так что можно долго и нудно моделировать и усё будет в порядке.
А зачем их моделировать?Сделаю я лучше пару временных тест каталогов и всё протестирую "наживую"
Это будет рукоблудство. Твой коллега взял твой код и запустил юниттесты - а они упали, потому что каталога нет. У тебя стоит билдсервер. Его дело строить приложение. Перед этим он прогоняет юниттесты. Тесты не прошли. А должны были, на билдсервере не должно быть точно воспроизведено окружение для запуска.
Если ты все делаешь на коленке, то ты можешь насиловать тесты как тебе угодно. Но если ты пишешь тесты напоказ или как учебное заданиe, то должен учитывать, что ты не знаешь, в каких условиях на фирме будут запушены тесты. И тестировать они должны правильно. Не то, что тебе хочется, а то, что можно и нужно. Для каждой цели свой инструмент.
Но Юниттест не может дать результат "на этом компе результаты неудовлетворительные
На так о чем я и говорю, что не нужны в данном случае юнит тесты, потому как все ситуации смоделировать невозможно.
Меня сейчас будущее не интересует, что кто то, что то, когда то сломает.
а они упали, потому что каталога нет
Так в тестах он и будет создаваться, всё с нуля, на "чистой системе".
Ну не вижу я никакого смысла делать море моделей и потом их настраивать. Приложение то показать и выбросить. Хотя и показывать то некому. Чисто для себя делаю.