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

unit tests

1806  1 2 3 4 все
Simple Nothing is f*cked06.11.18 16:36
Simple
NEW 06.11.18 16:36 
в ответ Программист 06.11.18 07:26
Роя Ошеровава

Кстати, эту книгу автору тоже неплохо было бы прочитать :)

#21 
Simple Nothing is f*cked06.11.18 16:38
Simple
NEW 06.11.18 16:38 
в ответ dymanoid 05.11.18 21:11
рефакторить огромную кодовую базу "чтобы юнит-тесты ввести".

Речь идет о самых примитивных рефакторингах типа Extract method. У Фезерса подробнее.

#22 
dymanoid знакомое лицо06.11.18 20:57
dymanoid
NEW 06.11.18 20:57 
в ответ Simple 06.11.18 16:38
Речь идет о самых примитивных рефакторингах типа Extract method.

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

#23 
  moose старожил06.11.18 21:54
NEW 06.11.18 21:54 
в ответ Simple 06.11.18 16:36

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


вот, предложу для примера желающим простой пример. не знаю, как его "в систему привести". что ф-я (читать: функция) делает, ясно из кода:


def get_suggestions (name):
    try:
        retval = []
        page = requests.get(u'https://blablabla?query={0}'.format(name))
        tree = html.fromstring(page.content)
        group = tree.xpath("//div[@class='some-group']")
        for item in group:
            name_nodes = item.xpath('.//div[starts-with(@class, "some-node")]')
            if name_nodes and len(name_nodes) == 3:
                retval.append(name_nodes[0].text)
                retval.append(name_nodes[2].text)
    except Exception, e:
        print e
    return retval
вроде ясно, что код делает, и вызывающий проверит, вернули ли хоть какие-нибудь имена. если нет - будет отправлено сообщение об этом. но у нас пока примитивная задача: написать юнит-тест для этой ф-ии (читать: функции). главный вопрос остается: что мы хотим протестировать? полагаю, что цель - проверить, выполняет ли ф-я (читать: функция) то, чего мы от нее ожидаем.
#24 
dymanoid знакомое лицо06.11.18 22:49
dymanoid
NEW 06.11.18 22:49 
в ответ moose 06.11.18 21:54, Последний раз изменено 06.11.18 22:49 (dymanoid)

Вот эта х-ня (читать: функция) - типичный пример божественного объекта. И швец, и жнец, и на дуде игрец. И в веб лезет, и контент получает, и XML парсит.

Её надо раздраконить на 2-3 отдельные, руководствуясь S и I из SOLID. Применяя D из SOLID. Не забывая про DRY при этом.

Тогда всё будет замечательно тестироваться.

#25 
Simple Nothing is f*cked06.11.18 23:06
Simple
NEW 06.11.18 23:06 
в ответ dymanoid 06.11.18 20:57

Конкретно эту проблему не решит, но поможет сделать методы поменьше, следовательно лучше тестируемыми.

Синглтоны мокаются без проблем.

#26 
Simple Nothing is f*cked06.11.18 23:09
Simple
NEW 06.11.18 23:09 
в ответ moose 06.11.18 21:54

Выделить page.content в качестве параметра, а дальше уже все просто.

#27 
dymanoid знакомое лицо06.11.18 23:21
dymanoid
NEW 06.11.18 23:21 
в ответ Simple 06.11.18 23:06

А ну-ка примерчик про синглтоны. На C# и без хот-патчинга и прочих танцев с бубном IL-кодом, плиз.

Типа:

bool MyMethod(string key)
{
    var data = MyService.Instance.GetData(key);
    return MyService.Instance.CheckData(data);    
}

class MyService
{
    public static MyService Instance { get; }
    private MyService()
    {
        MyRepository.Instance.Init();
        MyXrenZnaetChto.Instance.Init();
        ZachemStolkoSingletonov.Instance.Init();
    }
}

#28 
Simple Nothing is f*cked06.11.18 23:23
Simple
NEW 06.11.18 23:23 
в ответ dymanoid 06.11.18 23:21

Не, я по жабе. Но на сишарпе тоже должно быть что-то похожее.

#29 
dymanoid знакомое лицо06.11.18 23:25
dymanoid
NEW 06.11.18 23:25 
в ответ Simple 06.11.18 23:23

Нету. Только специальной переделкой (доработкой напильником) синглтонов.

#30 
  moose старожил06.11.18 23:30
NEW 06.11.18 23:30 
в ответ dymanoid 06.11.18 22:49

т.е. вы предлагаете, чтобы каждая ф-нкция содержала не более одного оператора? я могу это догнать только если ф-я становится слишком необъятной, и поэтому труднопонимаемой, или часть кода можно выделить в отдельную ф-ю, которая может использоваться другими. но вы бы лучше пояснили вашу идею , переиначив этот примитивный примерчик, "раздраконив его на 2-3 отдельніх, руководствуясь этими странными словами (S,I, ...)

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

#31 
  beatus Teddybär06.11.18 23:33
beatus
NEW 06.11.18 23:33 
в ответ dymanoid 06.11.18 22:49, Последний раз изменено 06.11.18 23:37 (beatus)
Нормальная функция. Из объектов увидел только X-Path и page. Всё оставить как есть, только добавить if для логов (см. моё предыдущее сообщение). Тесты писать не для функции, а для операций внутри функции.
P.S. программирую на Java, JavaScript и PHP
#32 
  moose старожил06.11.18 23:38
NEW 06.11.18 23:38 
в ответ Simple 06.11.18 23:09, Последний раз изменено 06.11.18 23:51 (moose)

зачем? если дело в том, чтобы проверить, умеет ли ф-я разыскивать в прочитанном с сайта полезное, то можно запэтчить requests mock'ом, который будет возвращать "правильный вариант", а потом - "неправильный". и мы увидим, работает ли наша примитивная ф-я как мы задумали. я вот почему-то вижу, что она может перестать работать только в единственном реальном случае: формат сайта изменится. и мне важно об этом как можно раньше узнать. а опасность, что кто-то пришлет "неправильный" параметр name - второстепенна. я просто не вижу НИКАКОЙ необходимости здесь что-то рефакторить, создавать юнит тэст вообще, кроме как "соблюдение ритуала". разубедите, если вы иначе считаете.


припомнилась одна история, когда потребовалось по протоколу передавать даты следующих событий. события могли проходить только по определенным дням в определенное время. и вот задается количество событий, скажем, 5, и в параметрах стоит, что события происходят по понедельниками, средам и субботам в 17:00. событие входит в рассмотрение, если до его наступления - не менее 15 минут. вот здесь я понаюниттэстовался вволю. наверное, какой-нибудь простенький тулчик помог бы, но тогда все было сделано "на колене": задаешь дату-время и количество событий, смотришь, возвращается ли тот список, что ожидаешь. кстати, не так сложно было этот наколенковый юниттест провести, как придумать сами тесткэйсиз.

#33 
dymanoid знакомое лицо06.11.18 23:41
dymanoid
NEW 06.11.18 23:41 
в ответ moose 06.11.18 23:30

Нужно почитать про SOLID - это альфа и омега современного ООП. Это не какие-то там вещи типа TDD, про которые все спорят (хорошо это или нет), а общепризнанные принципы разработки, которые значительно увеличивают качество кода и тем самым значительно уменьшают стоимость его поддержки.

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

#34 
  moose старожил06.11.18 23:53
NEW 06.11.18 23:53 
в ответ dymanoid 06.11.18 23:41

т.е. приведенный пример слишком сложен, чтобы пороиллюстрировать вашу идею? может, найдете таки пять минут? : )

#35 
Программист коренной житель07.11.18 07:02
NEW 07.11.18 07:02 
в ответ moose 06.11.18 21:54
главный вопрос остается: что мы хотим протестировать? полагаю, что цель - проверить, выполняет ли ф-я (читать: функция) то, чего мы от нее ожидаем.

:) Это так мой шеф говорит "мне надо, чтобы все работало" :)

А чего ты ожидаешь от этой функции? :D


Предположу, что requests - это какой-то объект, который возвращает какой-то другой объект.

Для того, чтобы сделать юнит-тест для этой функции нужна самая малость - подставить фейковый requests, который будет возвращать заранее известный объект page.

Далее делаешь 3 теста:

1) на странице нет div'ов class='some-group' -> результат пустое множество

2) на странице 1 div c class='some-group', но внутри группы нет some-node -> результат пустое множество

3) на странице 1 div c class='some-group', внутри группы 2 some-node, имя одной some-node'ы длиной 2 символа, а другой - 3 -> результат получаешь массив из одного элемента с заранее известным именем.


Понятно, что в реальности выделение групп и нод - более сложные процедуры, поэтому стоит подумать над тем, чтобы выделить эти процедуры в отдельные функции (и тестировать их по отдельности).


#36 
MrSanders старожил07.11.18 07:21
NEW 07.11.18 07:21 
в ответ Simple 06.11.18 23:23
Не, я по жабе. Но на сишарпе тоже должно быть что-то похожее.

Ну, в яве private static final тоже только через рефлекцию менять можно. Чем мы и занимались лет 5 для тестов, пока весь код в порядок приводили :)

Но. Самое страшное не в этом. Самое страшное это отловить все ссылки на такой синглтон, который нам для теста надо моком подменить. Потому что как рассуждает программизд? "Это же синглтон, не меняется, чем три раза A.getInstance() вызывать, я вызову его один раз и сохраню в своем статическом поле". И всё, мы приплыли. Хотя, надо признать они такое же и с "вставленными" DI полями делать норовят. Пока ручки не отобьешь.

#37 
Программист коренной житель07.11.18 07:23
NEW 07.11.18 07:23 
в ответ dymanoid 06.11.18 23:21

Во-первых, начнем с того, что синглтоны - это зло :) И нужно иметь очень важную причину, чтобы использовать синглтон.

Во-вторых, предусмотреть бэк дор для тестов - как нефиг делать (не знаю, что ты понимаешь под хот-патчингом, но никаких танцев с бубном :D) (кстати, твой вариант синглтона нерабочий, т.к. Instance всегда null) Вот пример синглтона с бэк дором:

class MyService
{
    public static MyService Instance { get; internal set; }
    private MyService()
    {
        MyRepository.Instance.Init();
        MyXrenZnaetChto.Instance.Init();
        ZachemStolkoSingletonov.Instance.Init();
    }
}

Далее остается добавить только [assembly: InternalsVisibleTo("MyTests")] и все.

#38 
MrSanders старожил07.11.18 07:42
NEW 07.11.18 07:42 
в ответ moose 06.11.18 23:53
т.е. приведенный пример слишком сложен, чтобы пороиллюстрировать вашу идею? может, найдете таки пять минут? : )

Я со своей стороны влезу. Допустим, вы решили что юнит-тест для этого метода важен и нужен.

А как вы будете проверять, например, что метод вернёт ошибку, если в ответе ваших div-ов не будет? Ведь URL сервера у вас жестко внутри метода вбит.

#39 
MrSanders старожил07.11.18 07:44
NEW 07.11.18 07:44 
в ответ Программист 07.11.18 07:23

ну всё же изменение кода только для нужд тестов не есть хорошо. Но иногда приходится.

#40 
1 2 3 4 все