Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
aquaMakc
476 / 389 / 68
Регистрация: 14.02.2014
Сообщений: 1,891
Завершенные тесты: 1
1

Разработка через тестирование. Насколько реально и необходимо?

06.11.2015, 13:08. Просмотров 3507. Ответов 92
Метки нет (Все метки)

Доброго времени суток.
Рискну поднять довольно холиварную тему, чтобы попытаться прояснить для себя этот вопрос.

Скажу сразу - ни в одном своём проекте не применял тестирование, просто как-то не задумывался на эту тему.
Читая статьи на хабре складывается ощущение, что не оборачивают в тесты свои программы только быдлокодеры и хелловорлдщики и что без теста программа не имеет права на существование.

Выдалась свободная минутка, решил восполнить этот пробел в своей работе. Т.к. на данный момент нет задач по разработке решил прикинуть насколько возможно обложить тестами предыдущие проекты. И внезапно выяснил, что это практически нереализуемо, поскольку:
1) Большая часть методов - обработчики событий, вызываемых UI, потоками, сторонним ПО или железом. В них входные данные нельзя строго описать и предвидеть, посему обработчики этих событий сами занимаются проверкой валидности входных данных.
2) Как правило ядро программы - стейт-машина, выполняющая задачу, зависящую от состояния ряда параметров, в том числе не являющихся входными аргументами при старте соответствующего метода. Причём получать входные данные стейт-машина может и в процессе выполнения обрабоки.
3) Оставшиеся методы либо выполняют элементарные сервисные функции, например вывод сообщения в лог, либо производят манипуляции с переменными программы, либо запускают/останавливают выполнение задач.

Ни один из этих вариантов невозможно проверить в отрыве от всей работы программы.

В статьях-же про тестирование обычно приводятся примеры проверки методов типа public int sum (int a, int b), и проверяется, что при входных данных 2 и 3 на выходе должно быть 5.

Неужели только у меня одного складывается ощущение бесполезности и искуственной завышенности значения разработки через тестирование?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.11.2015, 13:08
Ответы с готовыми решениями:

Насколько реально написать билинговую систему на ASP и не будет ли проблем с безопасностью ?
Насколько реально написать билинговую систему на ASP и не будет ли проблем с безопасностью, и есть...

Не работает пример из книги Экстремальное программирование. Разработка через тестирование
В книге на русском языке "Экстремальное программирование. Разработка через тестирование" на 59 стр....

Насколько реально написание простой игры
возможно ли на этом языке написать какую либо элементарную игру ,помогите если не сложно пожалуйста

Разработка через тестирование (TDD) на C++ с использованием фреймворка Google Test
Привет! Надеюсь, что моя видео-инструкция кому-то пригодится: ссылка Буду рад почитать любые...

Насколько это реально???
есть ли какаянить прога чтоб из песни делать минусовку??? Это вообще реально???

92
StudAssistant
Эксперт
34811 / 27003 / 5019
Регистрация: 17.04.2006
Сообщений: 49,622
06.11.2015, 13:08
Закажите контрольную, курсовую, диплом или любую другую студенческую работу здесь.
92
Storm23
Эксперт .NETАвтор FAQ
9199 / 4448 / 1616
Регистрация: 11.01.2015
Сообщений: 5,682
Записей в блоге: 34
06.11.2015, 13:38 2
Цитата Сообщение от aquaMakc Посмотреть сообщение
И внезапно выяснил, что это практически нереализуемо
Конечно нереализуемо.
Так вот смысл TDD как раз в том, что система разрабатывается таким образом, что бы ее модули можно было тестировать независимо. По мнению сторонников TDD такая система будет максимально декомпозирована и ее модули будут независимы друг от друга.

Цитата Сообщение от aquaMakc Посмотреть сообщение
Неужели только у меня одного складывается ощущение бесполезности и искуственной завышенности значения разработки через тестирование?
ИМХО это все нужно только для больших компаний с большим штатом сотрудников.
0
aquaMakc
476 / 389 / 68
Регистрация: 14.02.2014
Сообщений: 1,891
Завершенные тесты: 1
06.11.2015, 14:09  [ТС] 3
Цитата Сообщение от Storm23 Посмотреть сообщение
система разрабатывается таким образом, что бы ее модули можно было тестировать независимо
Наверно, я плохой архитектор. Я не представляю себе такой системы. Как впрочем и возможность реализации правила "не более 10 строк на метод".
0
Storm23
Эксперт .NETАвтор FAQ
9199 / 4448 / 1616
Регистрация: 11.01.2015
Сообщений: 5,682
Записей в блоге: 34
06.11.2015, 14:19 4
Цитата Сообщение от aquaMakc Посмотреть сообщение
Наверно, я плохой архитектор. Я не представляю себе такой системы.
Ну само по себе то это сделать несложно. Просто передавайте в методы интерфейсы вместо конкретных классов. В момент тестирования в качестве параметра передается мок (mock) - представляющий собой фиктивную заглушку имитирующую реальный объект. В момент рабочего запуска программы, вместо интерфейса передается реальный объект. Вот и все.
Другое дело, что это сильно усложняет архитектуру системы и объем кода. Это минус.
0
06.11.2015, 14:19
insite2012
Модератор
Эксперт .NET
4890 / 3842 / 1097
Регистрация: 12.10.2013
Сообщений: 11,101
Записей в блоге: 2
06.11.2015, 14:25 5
Цитата Сообщение от aquaMakc Посмотреть сообщение
ни в одном своём проекте не применял тестирование, просто как-то не задумывался на эту тему.
По правде говоря, аналогично. Нет, по мере написания каких-то компонентов возникает желание проверить их работу отдельно, перед тем как добавить в основную программу, но я обычно поступаю проще - создаю консольку и в ней пишу компоненты, в ней же и тестирую. А потом уже или добавляю класс в готовое приложение, либо перекомпилирую консоль как dll, предварительно удалив файл с точкой входа.
Возможно, из меня тоже архитектор никакой (поскольку не профессиональный кодер, а любитель), но вроде мне так удобно, и наверно это главное. Вроде все согласно основным правилам, классы и так далее, повторная используемость кода присутствует. А вот тестирование - это что-то для меня малопонятное.
0
Cupko
486 / 472 / 131
Регистрация: 17.07.2012
Сообщений: 1,399
Записей в блоге: 1
Завершенные тесты: 2
06.11.2015, 14:26 6
TDD != обложить тестами предыдущие проекты.
Чтобы обложить систему тестами, её надо изначально сделать тестируемой, за что отвечает архитектура. А архитектура обычно проектируется на старте. Если изначально тестируемость не закладывалась, ничего вы не обложите

Про 10 строк на метод - дело привычке, сначала заставьте себя следовать этому правилу. Когда статический анализатор не пропускает коммит с методом > N строк - тут ничего не поделаешь
0
aquaMakc
476 / 389 / 68
Регистрация: 14.02.2014
Сообщений: 1,891
Завершенные тесты: 1
06.11.2015, 14:43  [ТС] 7
Цитата Сообщение от Cupko Посмотреть сообщение
Про 10 строк на метод - дело привычке, сначала заставьте себя следовать этому правилу.
Боюсь, что это правило может довести до абсурда в виде дробления кода на кучу взаимо-зависимых методов.
Я стараюсь писать в ключе 1 метод = 1 задача.

Добавлено через 7 минут
Цитата Сообщение от Storm23 Посмотреть сообщение
В момент тестирования в качестве параметра передается мок (mock) - представляющий собой фиктивную заглушку имитирующую реальный объект
Может есть пример подобного кода на посмотреть, желательно не лабораторного, а боевого?
0
Cupko
486 / 472 / 131
Регистрация: 17.07.2012
Сообщений: 1,399
Записей в блоге: 1
Завершенные тесты: 2
06.11.2015, 14:50 8
Цитата Сообщение от aquaMakc Посмотреть сообщение
Боюсь, что это правило может довести до абсурда в виде дробления кода на кучу взаимо-зависимых методов.
Ну значит нужно научиться проектировать так, чтоб не писать кучу взаимно-зависимых методов. Для этого и существуют паттерны-антипаттерны.
Цитата Сообщение от aquaMakc Посмотреть сообщение
Я стараюсь писать в ключе 1 метод = 1 задача.
Границы для 1 задачи, как раз-таки выбираете вы.
0
Jupiter
Каратель
Эксперт С++
6577 / 3998 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
06.11.2015, 15:12 9
Цитата Сообщение от aquaMakc Посмотреть сообщение
1) Большая часть методов - обработчики событий, вызываемых UI, потоками, сторонним ПО или железом. В них входные данные нельзя строго описать и предвидеть, посему обработчики этих событий сами занимаются проверкой валидности входных данных.
говнокод, естественно такое нельзя протестировать без обезьяны которая будет кликать
1
IamRain
1543 / 1294 / 407
Регистрация: 02.08.2011
Сообщений: 3,822
06.11.2015, 15:17 10
Сам никогда не писал, но, по сути, с TDD проектирование сущностей будет более проработанным согласно SRP паттерну, потому что, когда пишешь тест ты должен грамотно определить все инварианты класса. Как результат, вероятность появления кривой архитектуры довольно низка, ятп. Отсюда и правило 10 строк на метод будет само собой разумеющееся.
Если взять за привычку, то это плюс к скилу архитектора , да и к качеству.
0
Storm23
Эксперт .NETАвтор FAQ
9199 / 4448 / 1616
Регистрация: 11.01.2015
Сообщений: 5,682
Записей в блоге: 34
06.11.2015, 16:08 11
Цитата Сообщение от aquaMakc Посмотреть сообщение
Может есть пример подобного кода на посмотреть, желательно не лабораторного, а боевого?
Да разве в интернете мало опенсурсных проектов с TDD? Смотрите любой.
Ну или дайте пример конкретного кода, попробуем его переделать.
0
aquaMakc
476 / 389 / 68
Регистрация: 14.02.2014
Сообщений: 1,891
Завершенные тесты: 1
06.11.2015, 17:04  [ТС] 12
Цитата Сообщение от Storm23 Посмотреть сообщение
Ну или дайте пример конкретного кода, попробуем его переделать.
ну например вот такой код. Выполняется, как Task. Программа представляет собой плагин для хоста.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
        /// <summary>
        /// Подключение к корректору и согласование скоростей
        /// </summary>
        /// <returns>Результат подключения к корректору</returns>
        bool initTask()
        {
            byte[] args = new byte[0];
            if (config.adress.Trim() != "")
                host.writeLog("Инициализация корректора с адресом " + config.adress, (int)logLevels.WARNING);
            else
                host.writeLog("Инициализация корректора", (int)logLevels.WARNING);
            args = EK270.EkOpen1Req(config.adress.ToString());
            if (!doSend(TEk270.clearCom, args, true))
                return false;
            String typeStr = String.Empty;
            if (!EK270.EkOpen1Ans(inArgs, ref typeStr))
            {
                host.writeLog("Ошибка корректора", (int)logLevels.ERROR);
                return false;
            }
            config.EkType = typeStr;
            changeTypeEvent();
            host.writeLog("Соединение с корректором " + config.EkType + " установлено", (int)logLevels.INFO);
            args = EK270.EkOpen2Req();
            if (!doSend(TEk270.clearCom, args, true))
                return false;
            if (!EK270.EkOpen2Ans(inArgs))
            {
                host.writeLog("Ошибка согласования скоростей", (int)logLevels.ERROR);
                return false;
            }
            host.writeLog("Скорости обмена с корректором согласованы", (int)logLevels.INFO);
            return true;
        }
Добавлено через 8 минут
Здесь я вижу возможность разбиения метода и недрения ещё большей защиты от неправильных входных данных, но как этот метод можно заранее протестировать - нет.

Добавлено через 27 минут
Или вот такой:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        // функция отправляет пользователю таблицу с активными подключениями
        void doRenewConnections(Tuser user, HttpListenerResponse response)
        {
            try
            {
                String newTable = tableBlank;
                ConnectionInfo[] connections = TNetServer.getLockedConenctions();    // получаем список подключенных клиентов
                String[] newCells = new String[7];
                newCells[0] = "ID";
                newCells[1] = "Имя";
                newCells[2] = "IP";
                newCells[3] = "Порт";
                newCells[4] = "Время соединения";
                newCells[5] = "Статус";
                newCells[6] = "О клиенте";
                bool isAllRights = false;
                if (user.Level == usersDispatcher.userLevel.ADMIN || user.Level == usersDispatcher.userLevel.SERVICE)
                    isAllRights = true;
                else
                    isAllRights = false;
                StringBuilder newRows = new StringBuilder(10000);
                newRows.Append(htmlText.getTableRow(newCells, true, isAllRights) + "\r\n");
                newTable = newTable.Replace(htmlText.placeTableHead, newRows.ToString());
                newRows.Clear();
                newRows.Append("<tbody>\r\n");
                for (int i = 0; i < connections.Length; i++)
                {
                    if (connections[i].id == 0)
                        continue;
                    if (isAllRights)
                        newCells[0] = "<input type="checkbox" id="" + connections[i].id.ToString() + ""/> " + connections[i].strId;
                    else
                        newCells[0] = connections[i].strId;
                    newCells[1] = connections[i].name;
                    newCells[2] = connections[i].strIp;
                    newCells[3] = connections[i].port;
                    newCells[4] = connections[i].connectTime.ToString("dd/MM/yyyy HH:mm:ss");
                    newCells[5] = connections[i].strStatus;
                    newCells[6] = connections[i].about;
                    newRows.Append(htmlText.getTableRow(newCells, false, connections[i].isFullRights) + "\r\n");
                }
                newRows.Append("</tbody>\r\n");
                newTable = newTable.Replace(htmlText.placeTableBody, newRows.ToString());
                String newData = "Всего подключений: " + connections.Length.ToString() + "\r\n";
                newData += "<p>" + newTable + "</p>";
                sendHtml(newData, response);
                Array.Clear(connections, 0, connections.Length);
            }
            catch (Exception ex)
            {
                outLog("Error of updating connections\r\n" + ex.ToString(), logLevel.ERROR);
                doError(user, response, "Ошибка обновления списка подключений");
            }
        }
Выполняется при получении POST-запроса на обновление таблицы html-страницы, отображающей подключенне в данный момент по TCP клиенты.
0
freeba
Неадекват
1309 / 1102 / 211
Регистрация: 02.04.2010
Сообщений: 2,551
Записей в блоге: 2
Завершенные тесты: 2
06.11.2015, 17:37 13
Цитата Сообщение от aquaMakc Посмотреть сообщение
Неужели только у меня одного складывается ощущение бесполезности и искуственной завышенности значения разработки через тестирование?
Не стоит сильно заморачиваться такими вещами. Следует помнить что хабр - это заповедник веб-программистов дружно прущихся от всяких стартапов и крупных софт-контор. Соответственно и все методологии, фреймворки и прочие плюшки используемые ими возводят чуть ли не в абсолют.

На деле: тесты для типового CRUD-приложения на WinForms нужны как телеге пятая нога, причем они скорее навредят т.к. придется делать лишний слой абстракций специально для тестов.

Другая сторона - WEB: Большинство современных веб-фреймворков построены на схеме MV*. И если в программе используется IoC контейнер, то написание юнит-тестов сильно упрощается. Да и сама архитектура сайтов этому способствует.

Вобщем, тестировать или не тестировать предмет холивара сравнимый с .NET vs Java. Кроме здравого смысла тут ничего не поможет
2
Jupiter
Каратель
Эксперт С++
6577 / 3998 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
06.11.2015, 17:39 14
Цитата Сообщение от aquaMakc Посмотреть сообщение
Выполняется при получении POST-запроса
Цитата Сообщение от aquaMakc Посмотреть сообщение
// функция отправляет пользователю таблицу с активными подключениями

если завтра вам скажут отправлять пользователю таблицу по почте то ваш код можно просто выкинуть
2
aquaMakc
476 / 389 / 68
Регистрация: 14.02.2014
Сообщений: 1,891
Завершенные тесты: 1
06.11.2015, 17:49  [ТС] 15
Цитата Сообщение от Jupiter Посмотреть сообщение
если завтра вам скажут отправлять пользователю таблицу по почте то ваш код можно просто выкинуть
) Не скажут, а принесут согласованное со мной-же ТЗ, как и то, по которому писался данный кусок кода. Стояла конкретная задача - реализация программы с web-интерфейсом. В данном конкретном случае у пользователя есть html страница, посреди которой таблица, обновляемая по технологии ajax.

Знаю, что можно было и по другому сделать, например, прикрутить jquery и слать ему json, но было отровенно лень разбираться ещё и с javascript фреймворками.
0
Jupiter
Каратель
Эксперт С++
6577 / 3998 / 400
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
06.11.2015, 18:37 16
Цитата Сообщение от aquaMakc Посмотреть сообщение
Не скажут, а принесут согласованное со мной-же ТЗ
вот в ТЗ и принесут. к чему я веду? а к тому что в вашем коде нет абстракций, вообще, от того и проблемы с тестированием, расширением и т.п.
0
sau
2158 / 1727 / 297
Регистрация: 22.07.2011
Сообщений: 6,529
Завершенные тесты: 1
06.11.2015, 19:00 17
но как этот метод можно заранее протестировать - нет.
Если бы при разработке классов и их методов , Вы оглядывались в сторону TDD принципов , и держали в голове возможность их тестирования (совсем не обязательно при этом писать сам тест) , то у Вас просто не было бы подобных каша-методов , ввиду правильной декомпозиции. Да и тестирование оберточных методов не особо нужно , если они в простом формате вызывают другие , уже протестированные и отлаженные методы.
А по поводу специфичного окружения - типа http контекста и т.п , то тут пишут специальные классы заглушки - fakes (например https://msdn.microsoft.com/ru-ru/library/hh549174.aspx) , которые эмитируют то или иное поведение.

Цитата Сообщение от insite2012 Посмотреть сообщение
Нет, по мере написания каких-то компонентов возникает желание проверить их работу отдельно, перед тем как добавить в основную программу, но я обычно поступаю проще - создаю консольку и в ней пишу компоненты, в ней же и тестирую.
Иногда это просто необходимо , когда нельзя проверить работоспособности отдельных компонентов сложного комплекса связанных приложений здесь и сейчас , простым запуском.
И консольный тест - да , можно , для парочки функций, но , когда у Вас хотя бы несколько десятков шатких методов , работоспособность которых нужно периодически проверять после каких либо правок , зачастую в казалось бы несвязанных местах (или если Вы сами не знаете как они могут быть связанны- например , работа ведется группой , или просто забыли нюансы взаимодействия) , тогда возникает необходимость в более серьезном подходе , и становится проще создать проект теста , который может интегрироваться с тест.инструментарием , когда одним легким движением руки Вы можете прогнать множество различных тестов , получить статистику , убедится что нигде ничего не поломалось , в консольном проекте такое делать просто очень неудобно и долго.
1
insite2012
Модератор
Эксперт .NET
4890 / 3842 / 1097
Регистрация: 12.10.2013
Сообщений: 11,101
Записей в блоге: 2
06.11.2015, 19:38 18
Цитата Сообщение от sau Посмотреть сообщение
если Вы сами не знаете как они могут быть связанны- например , работа ведется группой
К счастью, я работаю один, и все мои программы - плод моих задумок и моих же реализаций, так что у меня таких вопросов просто не возникает.
0
sau
2158 / 1727 / 297
Регистрация: 22.07.2011
Сообщений: 6,529
Завершенные тесты: 1
06.11.2015, 20:02 19
- хотя , это я уже больше о необходимости разработки тестов , нежели о разработке через тесты.
0
Storm23
Эксперт .NETАвтор FAQ
9199 / 4448 / 1616
Регистрация: 11.01.2015
Сообщений: 5,682
Записей в блоге: 34
07.11.2015, 12:37 20
Цитата Сообщение от freeba Посмотреть сообщение
Большинство современных веб-фреймворков построены на схеме MV*.
Не, стоп, MV* нужны и в винформсах. Без фанатизма конечно, но хотя бы отделение модели от интерфейса - необходимо.
Цитата Сообщение от Jupiter Посмотреть сообщение
если завтра вам скажут отправлять пользователю таблицу по почте то ваш код можно просто выкинуть
В целом я конечно согласен, что архитектура нужна. Но давайте смотреть трезво на вещи. Если автору завтра скажут отправлять по почте, то он просто напшет if(отправлятьПоПочте)ОтправитьПоПочте(). Вот и все. Да, некрасиво, да костыльно. Но по трудозатратам не сравнить с TDD. Конечно, после over 9000 правок приложение превратится в кашу. НО к тому времени уже и само приложение устареет или же будет полностью переписано уже с новым экспириенсом. И в целом этот цикл может оказаться значительно дешевле TDD.

aquaMakc,
Ну вы же тут сами видите что в коде у вас каша изначально. Куча каких-то глобальных переменных и статических классов, что уже - фэ. А ведь вы могли сделать интерфейс для вот этих всех EK270, и передавать их в метод как параметры. Хотя бы.

Добавлено через 8 минут
Цитата Сообщение от freeba Посмотреть сообщение
На деле: тесты для типового CRUD-приложения на WinForms нужны как телеге пятая нога
Вы правы, но так бывает не всегда. Вот представьте себе ситуацию: вы менеджер в крупной конторе. И вы выпускаете какое нибудь CMS. И вот у вас с одной стороны - 100 фирм-пользователей. А с другой стороны 100 индусов программистов. И вот каждому юзеру нужны какие-то особые плюшки к этой CMS. Одному одно, другому - другое. Фактически на каждого клиента создается отдельная версия приложения. И вот представьте КАК вы будете объяснять всем 100 программистам требования всех ваших 100 заказчиков? Вот просто представьте себе этот процесс. При том что часть программистов - в Индии работают удаленно.
Вот тут то вы и проникнитесь любовью к всяким TDD и т.п. технологиям, позволяющим сделать разделение труда
0
07.11.2015, 12:37
StackOverflow
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.11.2015, 12:37

Насколько реально поймать звук с 3-х метров ?
Есть электретный микрофон. Усилок хочу собрать по такой схеме.Пообещал знакомому сделать...

дизасм ATmega128, насколько реально разобраться?
задача следующая: есть бинарник от 128ой меги, необходимо понять высокоуровневый алгоритм ее...

Насколько реально закрепить масштаб страницы?
ВСЕМ ПРИВЕТ Подскажите насколько в принципе реально закрепить масштаб страницы таким образом...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru