Макет серии взаимозависимых вызовов - PullRequest
0 голосов
/ 03 января 2019

У меня есть метод, который очищает веб-страницу и сохраняет данные в файл (пример кода см. Ниже).Мне нужно проверить, что полученные данные правильно сформированы.

Проблема в том, что данные поступают из серии вызовов, а дальнейшие вызовы используют результаты предыдущих.Что еще хуже, многие из задействованных вызовов выполняются для одних и тех же объектов (Webdriver, WebDriverWait и expected_conditions) с разными аргументами.

Я вижу, что unittest.mock.Mock может высмеивать результат простого вызова или серии простых вызовов, но не может понять, как реализовать нечто запутанное, как это.Единственный способ, который я вижу, - вручную переопределить каждый вызов метода и скопировать аргументы, которые я передаю в метод, в эти реализации, чтобы они знали, что возвращать для каждого вызова.И сделайте это снова для каждого другого теста.Это звучит как настоящий кошмар для написания и поддержки: кода в несколько раз больше, чем самих тестов, и дублирование кода почти 1: 1.Поэтому я отказываюсь продолжать, пока кто-то не скажет мне, что есть лучший способ или не докажет, что его нет, и каждый действительно делает это так (что я не верю) и, например, переписывает все тесты каждый раз, когда изменяется метка на странице (это деталь реализации, поэтому обычно она не должна влиять на тестовый код).

Пример кода (адаптирован для http://example.com):

import selenium.webdriver
from selenium.webdriver.common.by import By as by
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def dump_accreditation_data(d, w, i, path):
    f = codecs.open(os.path.join(path, "%d.txt" % i), "w", encoding="utf-8")

    u = u'http://example.com/%s/accreditation' % i
    d.get(u)

    # page load
    w.until(EC.visibility_of_element_located((by.XPATH,"//p")))    #the real code has a more complex expression here with national characters
    w.until_not(EC.visibility_of_element_located((by.CSS_SELECTOR, '.waiter')))
    print >> f, u

    # organization name
    e = w.until(EC.visibility_of_element_located((
        by.CSS_SELECTOR, 'h1'
    )))
    org_name = e.text
    print >> f, org_name
    del e

    #etc
    e = d.find_element_by_xpath(u'//a[text()="More information..."')
    print >> f, e.get_attribute('href')

#How it's supposed to be used:
d = selenium.webdriver.Firefox()
w = WebDriverWait(d, 10)
dump_accreditation_data(d, w, 123, "<output_path>")

1 Ответ

0 голосов
/ 23 января 2019

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

На алгоритмическом уровне сравнительно мало кода, например:

os.path.join(path, "%d.txt" % i)

или

u = u'http://example.com/%s/accreditation' % i

или создание содержимого выходного файла.

То есть, если в коде есть ошибки, они с большей вероятностью окажутся на уровне взаимодействия: вызов правильных библиотечных функций справапорядок с правильными параметрами, параметры с правильными форматами и т. д. - Однако с макетами библиотек вы не найдете ошибок взаимодействия, потому что макеты реализованы вами и просто отражают ваше (потенциально неправильное) понимание библиотекиповедение.

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

Эти вспомогательные функции могут затемвсе тестируются с использованием юнит-тестирования.Остальную часть функциональности вы бы протестировали с помощью интеграционного тестирования.

...