Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Рефакторинг. Погружение




Рефакторинг

 

Погружение

Нравится Вам или нет, но баги случаются. Несмотря на все усилия при создании полных модульных тестов, баги всё равно существуют. Что я подразумеваю под словом «баг»? Баг - это тестовый случай который ещё не написан.

> > > import roman7> > > roman7. from_roman('') ① 0

① Собственно, баг. Вызов from_roman с параметром пустой строки (или любой другой последовательности символов не являющейся правильным римским числом) должен завершиться исключением InvalidRomanNumeralError.

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

class FromRomanBadInput(unittest. TestCase): . . . def testBlank(self):    '''from_roman should fail with blank string'''   self. assertRaises(roman6. InvalidRomanNumeralError, roman6. from_roman, '') ①

① Всё предельно просто: вызываем from_roman() с пустой строкой и проверяем, что выбрасывается исключение InvalidRomanNumeralError. Самое сложное было найти баг; теперь, когда известно, что такая ошибка существует, кодирование проверки не займёт много времени.

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

you@localhost: ~/diveintopython3/examples$ python3 romantest8. py -vfrom_roman should fail with blank string... FAILfrom_roman should fail with malformed antecedents... okfrom_roman should fail with repeated pairs of numerals... okfrom_roman should fail with too many repeated numerals... okfrom_roman should give known result with known input... okto_roman should give known result with known input... okfrom_roman(to_roman(n))==n for all n... okto_roman should fail with negative input... okto_roman should fail with non-integer input... okto_roman should fail with large input... okto_roman should fail with 0 input... ok ======================================================================FAIL: from_roman should fail with blank string----------------------------------------------------------------------Traceback (most recent call last): File " romantest8. py", line 117, in test_blank self. assertRaises(roman8. InvalidRomanNumeralError, roman8. from_roman, '')AssertionError: InvalidRomanNumeralError not raised by from_roman ----------------------------------------------------------------------Ran 11 tests in 0. 171s FAILED (failures=1)

Только теперь Вы можете исправлять баг.

def from_roman(s): '''convert Roman numeral to integer''' if not s:                                                              ①    raise InvalidRomanNumeralError('Input can not be blank') if not re. search(romanNumeralPattern, s):    raise InvalidRomanNumeralError('Invalid Roman numeral: {}'. format(s)) ②     result = 0 index = 0 for numeral, integer in romanNumeralMap:    while s[index: index+len(numeral)] == numeral:        result += integer       index += len(numeral) return result

① Требуется всего 2 строчки кода: явная проверка с пустой строкой и выброс исключения.

② Не уверен, упоминалось ли ранее в книге, поэтому пусть это будет последний трюк при форматировании строк. Начиная с Python 3. 1 разрешается опускать числа при использовании индексов позиции в строке форматирования. То есть, вместо использования {0} для ссылки на первый параметр метода format(), Вы можете писать {} и Python заполнит соответсвующиий индекс позиции за Вас. Это выполняется для любого количества аргументов: первые скобки {} равносильны {0}, вторые скобки {} равносильны {1} и так далее.

you@localhost: ~/diveintopython3/examples$ python3 romantest8. py -vfrom_roman should fail with blank string... ok ① from_roman should fail with malformed antecedents... okfrom_roman should fail with repeated pairs of numerals... okfrom_roman should fail with too many repeated numerals... okfrom_roman should give known result with known input... okto_roman should give known result with known input... okfrom_roman(to_roman(n))==n for all n... okto_roman should fail with negative input... okto_roman should fail with non-integer input... okto_roman should fail with large input... okto_roman should fail with 0 input... ok ----------------------------------------------------------------------Ran 11 tests in 0. 156s OK ②

① Тест на обработку пустой строки теперь проходит, значит баг исправлен.

② Все остальные тестовые случаи по прежнему выполняются без ошибок, а это значит, что при исправлении ошибки не мы не добавили новых. Самое время, чтобы остановиться править код!

Кодирование через написание тестов не облегчает процесс исправления багов. Для исправления простых ошибок (как в приведённом примере) необходимы простые тесты; сложные ошибки, конечно же, требуют сложных тестов. Если ведётся разработка проекта через тестирование, то может показаться, что фиксация бага займёт больше времени, так как Вам придётся найти строчки кода с багом (собственно, написать тестовый случай для проверки этих строчек) и затем исправить баг. Если тест опять завершается не успешно, то придётся разобраться верно ли был исправлен баг или сам тест содержит ошибки. Тем не менее, при длительной разработке эти исправления в коде-в тесте-в коде окупают себя, так как скорее всего баг будет исправлен с первого раза. Также, так как Вы можете легко перезапускать все тесты, включая новый, Вы навряд ли " испортите" старый код при фиксации бага. Сегодняшние модульные тесты завтра превратятся в тесты регрессии.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...