Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 25, 2011 19:52:54

Borigor
От:
Зарегистрирован: 2011-03-24
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

Доброго времени суток, господа!

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

class MyClass(TestClass):

def testFn(self, x):
seq1 = ['aaa', 'bbb', 'ccc', 'ddd', 'fff']
for s in seq1:
print x
Понятное дело, если метод фейлится на s=='ccc', то метод прекращает свою работу и до проверок функциональностей ‘ddd’ и ‘fff’ не доходит
Вот чтобы такого избежать, посетило меня желание переделать эти тестовые классы так, чтобы на основании имеющегося массива (неважно, статического или динамически подгружаемого при инициализации) динамически создавались необходимые методы, делающие одно и то же, но каждый со своим именем и работающий со своею тестируемой сущностью.
Вот что у меня получилось в результате экспериментов:
class MyClass():
seq1 = ['aaa', 'bbb', 'ccc', 'ddd', 'fff']

for s in seq1:
exec "def test%s(self): self.my_fn('%s')" % (s.capitalize(), s)

def my_fn(self, x):
print x


if __name__ == "__main__":
obj = MyClass()
for k in MyClass.__dict__:
if k.find('test') == 0:
m = getattr(obj, k)
m()
Надеюсь, что то же самое можно было бы реализовать элегантнее, но не нашел, как.
Прошу ваших мнений, предложений, конструктивной критики.



Офлайн

#2 Апрель 25, 2011 20:32:49

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

А почему нельзя было заловить и обработать выскакивающие исключения?



Офлайн

#3 Апрель 25, 2011 20:49:18

Borigor
От:
Зарегистрирован: 2011-03-24
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

doza_and
А почему нельзя было заловить и обработать выскакивающие исключения?
Если бы можно было хэндлить исключения, я бы с этим не заморачивался.
Увы, это не разрешено.
Базовый фреймворк так построен, что при возникновении исключения метод обязательно должен зафейлиться.



Офлайн

#4 Апрель 25, 2011 20:50:11

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Динамическое задание методов класса

Все хуже. Нужно посмотреть unittest:TestCase.run и сделать по подобию.



Офлайн

#5 Апрель 25, 2011 21:08:44

Borigor
От:
Зарегистрирован: 2011-03-24
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

Андрей Светлов
Все хуже. Нужно посмотреть unittest:TestCase.run и сделать по подобию.
собственно, это оттуда и есть:
      m = getattr(obj, k)
m()
но суть именно в том как поэлегантнее задать эти методы.
или я неправильно уловил суть совета?



Офлайн

#6 Апрель 25, 2011 21:33:20

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Динамическое задание методов класса

Собственно говоря зачем лепить методы, да еще и через варварский exec?
Давайте вы показываете кусочек кода, а там посмотрим.
Имеющиеся — никуда не годятся.
Мы говорим о unittest? Откуда это следует?
Если ваш MyClass — тестовый контейнер, то почему он не наследует TestCase?
Как делается “проверка правильности”? Простой print выглядит неубедительно.



Офлайн

#7 Апрель 25, 2011 22:23:16

Borigor
От:
Зарегистрирован: 2011-03-24
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

Андрей Светлов
Собственно говоря зачем лепить методы, да еще и через варварский exec?
Давайте вы показываете кусочек кода, а там посмотрим.
Имеющиеся — никуда не годятся.
Мы говорим о unittest? Откуда это следует?
Если ваш MyClass — тестовый контейнер, то почему он не наследует TestCase?
Как делается “проверка правильности”? Простой print выглядит неубедительно.
Вроде же достаточно раскрыл подоплеку необходимости этого:
необходимо проверить все(!) функциональности, которые сейчас проверяются в цикле в одном методе.
Трогать фреймворк (да, на базе unittest'а), я тоже не вправе, т.к. код не мой, и никто мне добро на это не даст.
Поэтому не существенно, на мой взглгяд, unittest это или нет
Чаще всего список функциональностей получается динамически, запросом к базе, поэтому я не могу при имплементации тестов наплодить 10-15 оберток-тестовых методов, вызывающих один и тот же метод.
Вот и не нашлось другого пути, кроме как динамически генерировать методы.
А вот как это лучше сделать, в этом и состоит мой интерес.

Тестовых классов (и методов в них) очень много, и все разные.. суть методов - ассерты.
print я применил лишь для наглядной проверки работоспособности решения.



Отредактировано (Апрель 25, 2011 22:23:37)

Офлайн

#8 Апрель 25, 2011 23:07:38

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Динамическое задание методов класса

Есть сферический конь с педальным приводом. Детали реализации не важны.
Как его улучшить?
Коня — не покажу, даже на полвзгляда. И не просите!
Вроде бы я достаточно раскрыл делали и прочие функциональные особенности?

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



Офлайн

#9 Апрель 25, 2011 23:20:08

Borigor
От:
Зарегистрирован: 2011-03-24
Сообщения: 8
Репутация: +  0  -
Профиль   Отправить e-mail  

Динамическое задание методов класса

Андрей, я ценю Ваше чувство юмора.
Только почему бы нам на абстрагироваться от unittest'а, и не рассмотреть вопрос, как он поставлен.
Вот Вы упомянули “варварский exec”, видимо имея в виду наличие более тонкого/правильного подхода к реализации сабжа?
Был бы признателен, если бы поделились идеями.



Офлайн

#10 Апрель 25, 2011 23:28:27

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Динамическое задание методов класса

Привет от наших психов — вашим. И так вроде бы абстрагировались до полной сферичности.
Тем не менее — держите:

>>> class A(object):
... pass
...
... for name in 'abc':
... setattr(A, name, lambda self, name=name: name)
...
... a = A()
... print a.a()
... print a.b()
... print a.c()
a
b
c
>>>



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version