Python for testers

Posts Tagged ‘заметки’

Разделение stdout и stderr в python nosetest

Written by Михаил Поляруш on . Posted in Автоматизация, Работаю, Разработка

Проблема: в python есть популярный xUnit фреймворк nose, которым пользуются довольно много людей.  Когда подключаешь nose к continuous integration, то хочешь чтобы результаты были максимально видимыми и репрезентативными.  Но вот есть одна проблема, всю выходную информацию nose записывает в один поток, либо stdout либо stderr.  А как же быть, если нам нужно показать часть в stderr, а часть в stdout?

Например 

Результат прогона полностью выводиться в stderr:

#1 Test 1 … ok
#2 Test 2 … FAIL
#3 Test 3 … ok
#4 Test 4 … ok
#5 Test 5 … FAIL

======================================================================
FAIL: Test 2
———————————————————————-
Traceback (most recent call last):
  File “/home/katerina/Desktop/my_tests/color.py”, line 11, in test_2
    self.assertEquals(1, 2)
AssertionError: 1 != 2

======================================================================
FAIL: Test 5
———————————————————————-
Traceback (most recent call last):
  File “/home/katerina/Desktop/my_tests/color.py”, line 23, in test_5
    self.assertEquals(1, 7)
AssertionError: 1 != 7

———————————————————————-
XML: nosetests.xml
———————————————————————-
Ran 5 tests in 0.004s

FAILED (failures=2)


А надо чтоб результат выводился в 2 потока:

#1 Test 1 … ok
#2 Test 2 … FAIL
#3 Test 3 … ok
#4 Test 4 … ok
#5 Test 5 … FAIL

======================================================================
FAIL: Test 2
———————————————————————-
Traceback (most recent call last):
  File “/home/katerina/Desktop/my_tests/color.py”, line 11, in test_2
    self.assertEquals(1, 2)
AssertionError: 1 != 2

======================================================================
FAIL: Test 5
———————————————————————-
Traceback (most recent call last):
  File “/home/katerina/Desktop/my_tests/color.py”, line 23, in test_5
    self.assertEquals(1, 7)
AssertionError: 1 != 7

———————————————————————-
XML: nosetests.xml
———————————————————————-
Ran 5 tests in 0.004s

FAILED (failures=2)

Вся соль в том, что nose основывает весь свой запуск на unittest. А в unittest используется механизм буферизации stdout и stderr, т.е. unittest все ловит, но в последствии все уходит в один поток. Этот поток по умолчанию stderr. Его конечно можно поменять, но все равно это запись содержимого прогона в один поток или stderr или stdout.

Решение: простое решение – это переопределить TextTestResult и TextTestRunner при запуске тестов. Смотрим пример:

import unittest
import sys
import nose
from nose.core import TextTestRunner
from nose.result import TextTestResult
from cStringIO import StringIO

class Tests(unittest.TestCase):

    def test_1(self):
        """Test 1"""
        print 'something'
        self.assertEquals(1, 1)

    def test_2(self):
        """Test 2"""
        self.assertEquals(1, 1)

    def test_3(self):
        """Test 3"""
        self.assertEquals(1, 1)

    def test_4(self):
        """Test 4"""
        self.assertEquals(1, 1)

    def test_5(self):
        """Test 5"""
        print 'something'
        raise AssertionError("error")
        self.assertEquals(1, 1)

if __name__ == '__main__':
    class MyTextTestResult(TextTestResult):

        def addError(self, test, err):
            print >> sys.stderr, "%r ... error\n\t%r" % (test, err)

        def addFailure(self, test, err):
            print >> sys.stderr, "%r ... failure\n\t%r" % (test, err)

        def addSuccess(self, test):
            print >> sys.stdout, "%r ... ok" % test

    class MyTextTestRunner(TextTestRunner):

        def __init__(self):
            TextTestRunner.__init__(self, stream=StringIO())

        def _makeResult(self):
            return MyTextTestResult(self.stream,
                                    self.descriptions,
                                    self.verbosity,
                                    self.config)

    nose.main(testRunner=MyTextTestRunner())

Пример можно скачать здесь https://github.com/polusok/nose-split-stderr-stdout. Это далеко не идеальное решение, но позволит Вам быстро решить вашу задачу.

Успехов и хорошего питонирования!

З.Ы. С 05.08 стартует следующая группа по обучению программированию на python для начинающих. Еще можно записаться!

Жизненные советы от Алекса Дубаса

Written by Михаил Поляруш on . Posted in Обыденное, Размышляю

Жизнь приносит нам слезы и радость, смех и разочарование. Люди, отношения, семья, здоровье, родители, зависть … Это лишь небольшая часть того, о чем мы думаем или, к сожалению, не думаем каждый день. А стоило бы. Ведь это и есть жизнь!

Да кстати о жизни, посмотрите видео. Не пожалеете!

А для тех, кто знает английский могут посмотреть английскую версию (оригинал) (как всегда, в СНГ сами сделать ничего не могут :) )

Тренинг основы автоматизации – отчет по следующей группе

Written by Михаил Поляруш on . Posted in Автоматизация, Тренинги

Провел очередной тренинг по основам автоматизации тестирования ПО. Собралась группа 13 человек из разных проектов и с разными навыками. Должен констатировать факт, что все-таки осведомленность специалистов начального и среднего уровня об автоматизации тестирования остается на низком уровне. А ведь в Украине выполняется множество  проектов по автоматизации.

Меня посетила мысль, почему так происходит. Автоматизация – это промежуточное звено перед чем-то большим. Очень мало людей остается именно в этой роли. Поэтому специалист по автоматизации тестирования существует в среднем 2-3 года, а потом движется дальше. Соответственно,  этим и объясняется количество людей, занятых в автоматизации. Хотя по истории проведения своих авторских тренингов должен сказать, что все больше людей интересуется автоматизацией. Потому что методы разработки ПО заставляют команды использовать автоматизацию, хотят они этого или нет. Без этого просто быстро нельзя поставить ПО заказчику. При этом получается определенная пропасть в знаниях между специалистами, которые знают автоматизацию и теми, кто ее не знает.

В общем, это лирика :) Тренинг прошел успешно. По балам приблизительно 4.6 из 5. Есть несколько моментов в тренинге, которые я переделаю, а также решил еще добавить немного live coding и живых демонстраций, чтобы тренинг стал более полезным и интересным. Фотографии прикладываю.


Скоро у меня стартует марафон тренингов. Группы полностью укомплектованы. Буду учить подрастающее поколение.

Python mock: добавление метода реального класса к mock объекту

Written by Михаил Поляруш on . Posted in Автоматизация, Работаю, Разработка

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

Так вот, в python есть прекрасная библиотека, которая называется mock. Все было бы хорошо, но к сожалению, у нее нет встроенных средств добавления метода реального класса к уже созданному mock экземпляру класса. Зачем это нужно? (Возможно спросите вы)

Например, вы разрабатываете класс и какой-то метод для него. Вам необходимо протестировать только этот метод класса не вызывая остальных. Как это можно сделать? Вот примерно где-то так:

from mock import Mock
import new

class RealClass(object):
	def other_method(self):
		self.attribute_initiated_earlier = "class value"
	
	def real_method(self):
		return [self.attribute_initiated_earlier, 'password']

fake_object = Mock(spec=RealClass())
class_method = object.__getattribute__(RealClass, 'real_method')
fake_object.real_method = new.instancemethod(class_method, fake_object, Mock)
fake_object.attribute_initiated_earlier = "new value"
print fake_object.real_method()

Как параметризировать docstrings в Python?

Written by Михаил Поляруш on . Posted in Автоматизация, Работаю, Разработка

Зачастую автоматизаторы сталкиваются с проблемой вывода в логи нужной информации. Ко мне обратилась коллега с вопросом параметризации docstrings в python. Хочу просто подвести пунктиками, что можно, а что нельзя делать с docstrings.

  • Вы можете указывать docstrings для модуля, класса, функции, метода
  • Все описания docstrings идут сразу же после определения какой-то сущности, т.е. сразу после класса, функции и т.д.
  • docstrings не могут быть параметризированны
  • docstrings это только строка и не более того

Для того, чтобы вам продемонстрировать, как работает python docstrings посмотрите на этот код:

"""module docstring"""
import unittest

def function():
	"""function docstring"""
	pass

class LoginTestCase(unittest.TestCase):
	"""class docstring"""

	def testLogin(self):
		"""method docstring"""
		pass

if __name__ == "__main__":
	print __doc__
	print function.__doc__
	print LoginTestCase.testLogin.__doc__
	print LoginTestCase.__doc__

Но все же, если вам например, нужно в docstrings что-то заменить, то вы наверное захотите сделать это так.

"""module docstring %s """ % myvariable

К сожалению, так работать код у вас не будет и когда вы будете обращаться к docstrings, то объект будет с типом None. И все же как туда вставить нужные данные для того, чтобы использовать docstrings в своих нуждах? Просто надо работать с строкой docstrings и все. Пример, вам нужно использовать docstrings метода для вывода чего-то там в лог. Как вы это можете сделать?

"""module docstring"""
variable = "some string"
import unittest

def function():
	"""function docstring"""
	pass

class LoginTestCase(unittest.TestCase):
	"""class docstring"""
	def testLogin(self):
		"""method docstring %%replace%%"""
		print LoginTestCase.testLogin.__doc__.replace(r"%%replace%%", variable)
		pass

if __name__ == "__main__":
    import unittest
    unittest.main()

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

Удачи и хорошего python программирования!

Twitter лента

autotestinfo

Как продолжить тест при случайном появлении попапа? http://t.co/tGqX8PjPzD

mpoliarush

http://t.co/9879JVgl21 automates tests written with QUnit, Jasmine, Mocha with Expect.js assertions, Dojo Objective Harness, or YUI Test.