Unit Test. Кто использует?
Это все вопросы относительно предмета тестирования.
И даже в твоем примере нет необходимости в тестировании всей программы. Достаточно создать форму, подменить IsValid и сделать пару тестов, которые бы валидировали правильность связывания.
Но Вы говорите - не надо тестировать, там ничего не может пойти криво.
Я говорю, что WPF тестировать не надо :) Не знависимо от того, используется ли DynamicResource или StaticResource или button.Enabled = false - WPF в любом случае работает без ошибок.
Может, уже не в тему мои 5 копеек, но сегодня вот пришло в голову: Agile нужен для того, чтобы продукт-оунеры/менеджеры ничерта не делали. В смысле, совсем ничерта, на каждый конкретный запрос "нам нужен детально проработанный сценарий/юзкейс/бэклог" отвечая "вот вам в общих чертах, остальное по ходу дела, ибо Agile. У вас же архитектура масштабируется? Тестами все покрыто? Вот и работайте, и не парьте меня своим планированием".
Agile нужен для того, чтобы продукт-оунеры/менеджеры ничерта не делали.
Не-а, делать им как раз постоянно что-то надо. Метаться между командой и "акционерами" (stakeholder)
вот вам в общих чертах, остальное по ходу дела, ибо Agile
В скраме не выйдет. В общих чертах добавить историю в бэклог - пожалста. Но пока не будет выполнено Definition of Ready (DoR) история а спринт не перенимается. На ревью проработали детально, тогда и программировать можно.
Неприятным сюрпризом для новообращенных скрамистов как раз таки становится количество времени, которое тратится на всевозможные планирования и согласования, тут тебе и пара ревью за спринт и ретроспектива и планирование спринта. А по идеологии во всем этом должна участвовать вся команда. Плюс скрам-мастер. У нас >25% (скорее 30%) рабочего времени скрам-команд уходят на всяческие
совещания.
Планирование на ранней стадии - да, такого нет. Но определить "критерии качества" и "ограничивающие условия" (quality criteria, non-functional requirements) можно (и нужно для нового продукта) в т.н. "нулевом спринте". Архитектор(ы), product owner и stakeholder-ы должны определиться с "дорогими" (для изменения) вопросами.
Имхо, главная проблема agile вообще и scrum-а в часности это отсутствие понимания процесса у клиента.
Чаще всего сталкиваемся с "а почему такая мелочь так дорого стоит, что нельзя было раньше подумать и сразу сделать как надо".
Собирался в тяпницу, но свалилась работа...
Зато будет неделька поискать решение...
Код - в аттачменте.
Методы, которые не получалось переработать следующие:
- loadDtStock_allBcds_loadInoiveNo_byOrder()
- loadDtStock_allBcds_loadInoiveNo_byLoad()
- loadRackNos()
может что и упустил.
Если интересует DXCR48 - могу запостить. Но там нет ничего интересного - строится СЯЛ-строка и результат возвращается как ДатаТабле.
loadDtStock_allBcds_loadInoiveNo_byOrder()
Тут проблема только одна - DXCR48.loadDtInvoiceNo_byItem (...)
Я не знаю что это за функция, но ее надо закрыть заглушкой и тестировать так, как будто эта функция работает без ошибок.
Насколько я понимаю, DrOrder и DtInvoiceNo - это просто объект с данными, который тебе придется заполнять руками. Не могу сказать, понадобится ли тебе тут свой функционал.
loadDtStock_allBcds_loadInoiveNo_byLoad()
тут все также, как и в предыдущем случае - понадобится заглушка на DXCR48.loadDtInvoiceNo_byLoad(...) и DXCR48.loadDtInvoiceNo_byItem (...).
Единственное, что меня тут смущает - это DtInvoices.Compute(...) . Наверное придется таки делать обертку над DataTable.
loadRackNos()
тут самое интересное :)
DataTable таки придется подменить своей реализацией.
И при вызове DtStockOrderItems.Select() возвращать свои данные.
Насколько я понял, DataTable - это данные из БД. Тут ты можешь либо пойти на компромисс и отказаться от обертки над DataTable (думаю, что это не так просто, тем более, что еще и данными надо нашпиговывать), вместо этого сделать тестовую ДБ, и перед каждым тестом обнулять ее. Ну и наполнять данными только для одного теста.
Это, конечно, не будет уже юнит-тестом, но возможно это будем разумным компромиссом. Это уже только ты можешь оценить.
Ну а DXCR48.loadDtInvoiceNo_byLoad(...) и DXCR48.loadDtInvoiceNo_byItem (...) надо будет тестировать отдельно. Я так понимаю, что это статические функции? Или DXCR48 - это синглтон?
Тут проблема только одна
-----
Первая проблема в этом коде - то, что он не объектный.
Насколько я понимаю, DrOrder и DtInvoiceNo - это просто объект с данными
-----
Угу... Причем оба - типа ДатаРов... и вполне взаимозаменяемые... Мало того что взаимозаменяемые, так еще и оба используются как источник параметров... От этого вокруг накручена логика, которая размазана и непонятна...
понадобится заглушка на
-----
Я чуток сошлюсь вперед - "Это, конечно, не будет уже юнит-тестом..." - Ну а раз ЭТО все одно не юнит-тест, то может и не надо заглушек?
Во-первых - все одно не изолированный тест, во-вторых - данные - там достаточно много набивать - у меня на это (сорцы ты уже мог оценить) времени нет.
В общем делаю так - данные берутся из пром.базы и по ним считается "что там надо". Заодно отлаживается и конвертация СЯЛ - там изменения редки, элементарны, ошибки обнаруживаются почти сразу текущими тестами, отдельных тестов нет.
DataTable таки придется подменить своей реализацией
-----
Неее, не буду... во-первых - полную реализацию врапить долго. во-вторых - есть проблема - результат Селекта - ДатаРов-аррай - у меня врапируется в отдельный тип, который тестится. Этот тип имеет свой Селект. Точно такой же. И из-за этого Селекта там создается вторая таблица из которой и делается выборка. А это создает нерешаемую проблему - строки второй выборки - это не оригинальные строки из первичной таблицы. В общем - мне больше нужна правильная реализация Селекта для ДатаРов-аррай, чем
полный враппер ДатаТабле.
меня тут смущает - это DtInvoices.Compute(...)
-----
Это - самое простое - оно выносится в класс таблицы/субсета и там легко и просто заменяется на пересчет ЛИНКом... до тех пор пока не передается фильтр... с фильтром - труба... пока.
вместо этого сделать тестовую ДБ, и перед каждым тестом обнулять ее.
-----
Аккурат над этим сегодня сижу...
Даже проще - нужно гарантировать, что никто и никогда не сможет запустить тесты на пром.базе. Вот над этим и думаю... Вставка чего-нибудь в зазорчик - не устраивает - какой-нибудь идиот обязательно вставит... пусть временно... а потом точно забудет и потрет нахрен актуальную базу - завод встанет...
В переработанном виде те три метода, об которых шла речь сейчас выглядят так (см. аттач.). На них хоть что-то понятно...
В общем - мне больше нужна правильная реализация Селекта для ДатаРов-аррай, чем полный враппер ДатаТабле.
-----
Если кто знает где лежит оригинальный Селект - киньте ссылкой. Мне нужно чтобы исходный материал был ДатаРов-аррай, результат - ДатаРов-аррай, параметры - строковые.
Как вариант - автоконвертер из параметров в линк.
Читаю Ошерова (треть прочел). Пока что многовато того, что я уже знал (из книги Физерса, которую Ошеров тоже часто упоминает), но некоторые советы типа "только один мок на тест" уже наталкивают на правильные мысли. От .нет удается пока что успешно абстрагироваться :)
Нда-с, посмотрел я что Ошеров называет моками.
The main thing to remember about mocks versus stubs is that mocks are just like stubs, but you assert against the mock object, whereas you do not assert against a stub.
Загнался он. Для меня моки по Фаулеру - "объект с запрограммированными ожиданиями".
А мне нравится его классификация.
Слишком далеки они от народа (с). По крайней мере в яве. Все три основных фреймворка для создания "test doubles" (EasyMock, jMockit, Mockito) понимают под моками "объекты с поведением / ожиданиями". И все они позволяют "легким движением руки" собирать данные с помощью моков, чтобы их проверять. (т.е. одной строчкой превратить объект из стаба в мок).
Вот, кстати, Фаулер: http://martinfowler.com/articles/mocksArentStubs.html
по-моему, вполне похоже на ошеровские выкладки. Все пока не читал, сохранил в инсту :)
Чем же оно похоже-то? У Фаулера:
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
Т.е. стабы это "заглушки". Программируем то что надо, что не надо оставляем пустым, где надо что-то собрать - храним. Моки - "имитаторы", декларируем поведение для вызовов - тут верни 1, тут брось эксепшен.
Сегодня моки спокойно собирают данные, отличать стаб от мока по этому признаку бессмысленно. Поэтому мое имхо - различие между моками и стабами (фейками) в том что для моков мы оптисываем поведение а стабы/фейки - просто тупые/не очень тупые реализации интерфейсов.
Ну так точно как оно и у Ошерова. То есть, мок нужен, чтобы доказать, что вызов метода был, а стаб - чтобы вернуть нужное значение или протестировать состояние.
То ли я такой косноязыкий, то ли мы друг друга не можем понять по какой-то другой причине.