Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Юнит тесты для "системного" приложения

2301  1 2 3 4 5 6 7 8 9 все
AlexNek патриот15.04.21 12:56
AlexNek
NEW 15.04.21 12:56 
в ответ Программист 15.04.21 12:21
И как, ответ-то уже есть?

В смысле? На какой вопрос?


Не понимаю.

Ну вот кусок кода для настройки. Вроде всё верно. А гад реагирует на копирование каталога.


_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. И фиг поймешь как работает система, когда оно везде. И непонятно как отлаживать. Был уже такой проект.


Но есть и другие способы.

и какие интересно?

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

Вот например, в заглушке фиг бы додумался сразу - файл нужно вначале загнать в зип и при создании зип файла будет "ложное" извещение о копировании файла в каталог.

#21 
Программист коренной житель15.04.21 13:36
NEW 15.04.21 13:36 
в ответ AlexNek 15.04.21 12:56
На какой вопрос?

Что ты хочешь тестировать?


Ну вот кусок кода для настройки. Вроде всё верно. А гад реагирует на копирование каталога.
_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
    }



и какие интересно?

Ну например тоже сделать виртуальную функцию, которая будет возвращать реальную обертку. В тесте такую функцию можно перегрузить.


#22 
koder патриот15.04.21 13:45
koder
NEW 15.04.21 13:45 
в ответ AlexNek 15.04.21 12:04
Я только хочу проверить работу проги на граничных условиях.

Тогда берем прогу и проверяем. Именно прогу. Именно в определенном окружении. Это не юниттесты.

#23 
koder патриот15.04.21 13:47
koder
NEW 15.04.21 13:47 
в ответ AlexNek 15.04.21 12:35
"E:\\Alex\\WinCatalog" - каталог


Это не каталог. Это строка. В принципе путь к файлу, но вообще строка.

#24 
koder патриот15.04.21 13:55
koder
NEW 15.04.21 13:55 
в ответ AlexNek 15.04.21 12:43
reentrancy


Попробуй на примере сформулировать, что конкретно ты хочешь протестировать, увеличив количество файлов? То, что ты тестируешь - это ТВОЙ код или ты пытаешься посмотреть, как работает сторонняя библиотека? Именно твой код меняет поведение от количества файлов?


Могу логов нафигачить если не веришь, хоть и не проверял еще

Не надо. Опиши словами. Что должно произойти от увеличения количества файлов? Если ты используешь слова "быстрее", то это производительность.

и что тут тестировать

Только выzов самой функции. Вызывается и сколько раз вызывается. Это не твой код. Тут нечего тестировать.

#25 
AlexNek патриот15.04.21 13:58
AlexNek
NEW 15.04.21 13:58 
в ответ Программист 15.04.21 13:36
На какой вопрос? Что ты хочешь тестировать?

Вообще то не вижу ничего, что имеет смысл покрывать юнит тестами.

Можно только создать сферического коня в вакууме и его тестировать смущ


Это мило, то тут ты конфигурируешь некий объект _watcher. Никакой логики тут нет

Естественно, но именно так и не работает


Нужно было добавить еще одну строку

_watcher.NotifyFilter = NotifyFilters.FileName;


А что ты там тестируешь я так и не понял, для меня это какое то извращение, тем более что я пользую NUnit


#26 
AlexNek патриот15.04.21 14:03
AlexNek
NEW 15.04.21 14:03 
в ответ koder 15.04.21 13:47
Это не каталог. Это строка. В принципе путь к файлу, но вообще строка.

ну так в том то и дело. Не имеет значения, что я кидаю файл или каталог на выходе одна и таже строка.

И там еще буфер в 4К по умолчанию. Так что неизвестно будет ли работать для 1000 файлов и больше.

#27 
AlexNek патриот15.04.21 14:11
AlexNek
NEW 15.04.21 14:11 
в ответ koder 15.04.21 13:55
Если ты используешь слова "быстрее", то это производительность.

В данном случае от скорости меняется логика.

Я начинаю вызывать функцию по новому, когда она еще не закончила свою работу.


Кроме того как в "эмуляторе" отследить что эта функция создала новый файл к каталоге для мониторинга


Только выzов самой функции. Вызывается и сколько раз вызывается.

А на кой мне эвент тестировать? Сколько раз его вызвал столько и придет, вроде как системная функция.

#28 
AlexNek патриот15.04.21 14:13
AlexNek
NEW 15.04.21 14:13 
в ответ koder 15.04.21 13:45
Тогда берем прогу и проверяем

Ну так это я и сам могу сделать, только хорошо бы иметь это на автомате.

На одном компе запустить, потом на другом.

#29 
Программист коренной житель15.04.21 14:26
NEW 15.04.21 14:26 
в ответ AlexNek 15.04.21 13:58
Вообще то не вижу ничего, что имеет смысл покрывать юнит тестами.
Можно только создать сферического коня в вакууме и его тестировать
Можно. А можно задуматься о том, где могут быть проблемы в твоем коде и как смоделировать эти проблемы.

Короче говоря можно попробовать ответить на следующие вопросы:

1) что является твоим Unit under test?

2) какие требования предъявляются к твоему Unit under test?

3) с какими объектами взаимодействуешь твой Unit under test?


Ну и после того, как это все станет понятно, можно будет приступать к самим тестам.


Естественно, но именно так и не работает

ОК, что именно не работает в приведенном тобой коде?


А что ты там тестируешь я так и не понял

Тестируется setter проперти EnableRaisingEvents.


тем более что я пользую NUnit

Какая разница, в какой среде ты это тестируешь? NSubstitute - это библиотека для mock.


#30 
koder патриот15.04.21 14:59
koder
NEW 15.04.21 14:59 
в ответ AlexNek 15.04.21 14:03
Не имеет значения, что я кидаю файл или каталог

Во первых ты не можешь кинуть файл. Кинуть можно обьект класса или базисный тип как параметр. Мы же внутри программного кода. Файл - это понятие файловой системы. В коде файловой системы нет, есть обьекты определенных классов с определенными параметрами. Вот это и тестируем


И там еще буфер в 4К по умолчанию.

где там? как твой код взаимодействует прямо или косвенно с буфером, что может произойти, какой ответ ты можешь получить?

#31 
koder патриот15.04.21 15:03
koder
NEW 15.04.21 15:03 
в ответ AlexNek 15.04.21 14:13
На одном компе запустить, потом на другом.

Железное правило номер 0 - юниттесты дают одинаковые результаты вне зависимости от окружения. И даже в отсутствии этого самого окружения вообще. Иначе это интеграционные тесты.

#32 
koder патриот15.04.21 15:06
koder
NEW 15.04.21 15:06 
в ответ AlexNek 15.04.21 14:11
А на кой мне эвент тестировать? Сколько раз его вызвал столько и придет, вроде как системная функция.


Не в этом дело. При определенных обстоятельствах в твоем коде может не дойти до вызова этой функции. Юниттест проверяет эти условия. Шаловливый коллега мог закоментировать вызов или заменить функцию другой. Юниттест защищает от этого. Но Юниттест не может дать результат "на этом компе результаты неудовлетворительные, компьютер медленный". В смысле может конечно, написать можно что угодно, но это будет неправильно. Юниттесты не снимают метрики.

#33 
AlexNek патриот15.04.21 16:13
AlexNek
NEW 15.04.21 16:13 
в ответ Программист 15.04.21 14:26
Тестируется setter проперти EnableRaisingEvents.

А причем тогда файловая система?

System.IO.File.GetAttributes(path);


где могут быть проблемы в твоем коде и как смоделировать эти проблемы

А зачем их моделировать?

Сделаю я лучше пару временных тест каталогов и всё протестирую "наживую"


ОК, что именно не работает в приведенном тобой коде?

В приведенной версии, если я перемещаю каталог в директорию которая мониторится, возникает событие о создании объекта.

#34 
AlexNek патриот15.04.21 16:18
AlexNek
NEW 15.04.21 16:18 
в ответ koder 15.04.21 14:59
Мы же внутри программного кода

Не мы а Вы смущ

Я говорил о реальном тесте, который мне нужен.


где там?

В 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.


Если дофига файлов накидаю, могу ничего и не получить. Так что можно долго и нудно моделировать и усё будет в порядке.

#35 
koder патриот15.04.21 16:25
koder
NEW 15.04.21 16:25 
в ответ AlexNek 15.04.21 16:13
А зачем их моделировать?Сделаю я лучше пару временных тест каталогов и всё протестирую "наживую"

Это будет рукоблудство. Твой коллега взял твой код и запустил юниттесты - а они упали, потому что каталога нет. У тебя стоит билдсервер. Его дело строить приложение. Перед этим он прогоняет юниттесты. Тесты не прошли. А должны были, на билдсервере не должно быть точно воспроизведено окружение для запуска.


Если ты все делаешь на коленке, то ты можешь насиловать тесты как тебе угодно. Но если ты пишешь тесты напоказ или как учебное заданиe, то должен учитывать, что ты не знаешь, в каких условиях на фирме будут запушены тесты. И тестировать они должны правильно. Не то, что тебе хочется, а то, что можно и нужно. Для каждой цели свой инструмент.


#36 
AlexNek патриот15.04.21 16:26
AlexNek
NEW 15.04.21 16:26 
в ответ koder 15.04.21 15:06
Но Юниттест не может дать результат "на этом компе результаты неудовлетворительные

На так о чем я и говорю, что не нужны в данном случае юнит тесты, потому как все ситуации смоделировать невозможно.

Меня сейчас будущее не интересует, что кто то, что то, когда то сломает.

#37 
Murr патриот15.04.21 16:27
Murr
NEW 15.04.21 16:27 
в ответ AlexNek 15.04.21 10:56

Это же целую модель системы надо делать.

------

Наконец-то ты это осознал!!!

Когда Я говорил, что таскаю данные из живой базы потому как не именю времени на написание всех тестов было таки непонятно почему... спок

#38 
AlexNek патриот15.04.21 16:30
AlexNek
NEW 15.04.21 16:30 
в ответ koder 15.04.21 16:25
а они упали, потому что каталога нет

Так в тестах он и будет создаваться, всё с нуля, на "чистой системе".

Ну не вижу я никакого смысла делать море моделей и потом их настраивать. Приложение то показать и выбросить. Хотя и показывать то некому. смущ Чисто для себя делаю.

#39 
Murr патриот15.04.21 16:33
Murr
NEW 15.04.21 16:33 
в ответ AlexNek 15.04.21 11:17

А может нужно это всё в очередь записывать?

-----

Конечно нужно. Только не в очередь, а проверять дату/время созадния файла по событию.

Копирование, надеюсь, у тебя идет в отдельном потокe?

#40 
1 2 3 4 5 6 7 8 9 все