Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Oct 15, 2012

How to run Selenium in background in virtual display (Xvfb)

http://en.wikipedia.org/wiki/Xvfb

In the X Window System, Xvfb or X virtual framebuffer is an X11 server that performs all graphical operations in memory, not showing any screen output. From the point of view of the client, it acts exactly like any other server, serving requests and sending events and errors as appropriate. However, no output is shown. This virtual server does not require the computer it is running on to even have a screen or any input device. Only a network layer is necessary.

Xvfb is primarily used for testing

PyVirtualDisplay - a Python wrapper for Xvfb:
#!/usr/bin/env python

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=0, size=(800, 600))
display.start()

# now Firefox will run in a virtual display. 
# you will not see the browser.
browser = webdriver.Firefox()
browser.get('http://www.google.com')
print browser.title
browser.quit()

display.stop()
http://stackoverflow.com/questions/6183276/how-do-i-run-selenium-in-xvfb

Aug 6, 2012

Tox to test across Python versions

Tox as is a generic virtualenv management and test command line tool you can use for:
  • checking your package installs correctly with different Python versions and interpreters
  • running your tests in each of the environments, configuring your test tool of choice
  • acting as a frontend to Continuous Integration servers, greatly reducing boilerplate and merging CI and shell-based testing.

Jul 30, 2012

Python 3.1 unittest2 framework new features

skip, skipIf and skipUnless decorators
class MyTestCase(unittest.TestCase):

    @unittest.skip("demonstrating skipping")
    def test_nothing(self):
        self.fail("shouldn't happen")

    @unittest.skipIf(mylib.__version__ < (1, 3),
                     "not supported in this library version")
    def test_format(self):
        # Tests that work for only a certain version of the library.
        pass

    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
    def test_windows_support(self):
        # windows specific testing code
        pass
expectedFailure decorator
class ExpectedFailureTestCase(unittest.TestCase):
    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, "broken")

Jun 18, 2012

Jun 4, 2012

Cynic

Cynic - Test harness to make your system under test cynical

http://vimeo.com/43375697

Apr 16, 2012

What type of test to write?

  • Write system tests for your views.
  • Write Selenium tests for Ajax, other JS/server interactions.
  • Write unit tests for everything else (not strict).
  • Test each case (code branch) where it occurs.
  • One assert/action per test case method.

Change settings in tests

@override_settings(ALLOW_COMMENTS=True)
def test_comments_allowed(self):
  # ...
https://github.com/carljm/django-testing-slides/blob/master/settings/30_good.md

Imposing no-DB discipline

from django.utils.unittest import TestCase

import mock

cursor_wrapper = mock.Mock()
cursor_wrapper.side_effect = RuntimeError("No touching the database!")


@mock.patch("django.db.backends.util.CursorWrapper", cursor_wrapper)
class NoDBTestCase(TestCase):
    """Will blow up if you database."""
https://github.com/carljm/django-testing-slides/blob/master/models/30_no_database.md

Selenium first test

http://habrahabr.ru/post/141994/

Лучше использовать Webdriver а не Selenium RC

Apr 13, 2012

Testing models, forms

Form
Django Forms Deep Dive - Nathan R. Yergler
import unittest

class FormTests(unittest.TestCase):
    def test_validation(self):
        form_data = {
            'name': 'X' * 300,
        }

        form = ContactForm(data=form_data)
        self.assertFalse(form.is_valid())
Eventbrite just released a library on GitHub called rebar – https://github.com/eventbrite/rebar
from rebar.testing import flatten_to_dict

form_data = flatten_to_dict(ContactForm())
form_data.update({
        'name': 'X' * 300,
    })
form = ContactForm(data=form_data)
assert(not form.is_valid())
ModelForm
class ModelFormTests(unittest.TestCase):
    def test_validation(self):
        form_data = {
            'name': 'Test Name',
        }

        form = ContactForm(data=form_data)
        self.assert_(form.is_valid())
        self.assertEqual(form.instance.name, 'Test Name')

        form.save()

        self.assertEqual(
            Contact.objects.get(id=form.instance.id).name,
            'Test Name'
        )
FormSet
from rebar.testing import flatten_to_dict, empty_form_data

formset = ContactFormSet()
form_data = flatten_to_dict(formset)
form_data.update(
    empty_form_data(formset, len(formset))
)
Model
Fast test, slow test by Gary Bernhardt
def test_that_spam_posts_are_hidden(self):
    post = Post(mark_post_as_spam=True)
    discussion = Discussion(posts=[post])
    assert discussion.visible_posts == []

Feb 17, 2012

Test Django transaction using mocking and TransactionTestCase

It's pretty simple using mock side_effect:
class MyTransactionTestCase(TransactionTestCase):
    fixtures = ['some_fixture.json',]

    @patch.object(SomeObjectInsideTransaction, 'some_method')
    def test_disable_transaction(self, some_method):
        some_method.side_effect = IOError("Unexpected exception")

        try:
            self.client.get('/your/view/url/')
        except IOError:
            pass

        # assertions here
You have to use TransactionTestCase:
Django TestCase classes make use of database transaction facilities, if available, to speed up the process of resetting the database to a known state at the beginning of each test. A consequence of this, however, is that the effects of transaction commit and rollback cannot be tested by a Django TestCase class. If your test requires testing of such transactional behavior, you should use a Django TransactionTestCase.

Feb 14, 2012

BDD (Lattuce и Splinter)

BDD (Behaviour Driven Development) - тесты пишутся на native english т.е. в итоге их смогут писать не программисты (тестировщики, кодеры или менеджеры)

Видео: http://python.mirocommunity.org/video/5169/djangocon-2011-testing-with-le
Используется Lattuce и надстройка над Selenium - Splinter


Видео: http://www.youtube.com/watch?v=OMLDHNaUMB8
Freshen + Behave

Feb 2, 2012

Chaos Python

Add this into your functional tests and smoke it.
import sys, random

def chaos_trace(frame, event, arg): 
   if event == 'line' and random.random() < 0.000001: 
       raise MemoryError()
   return chaos_trace

sys.settrace(chaos_trace)
You will get some lovely random failures injected into your code. A great way to find bugs, and make sure your reasoning is sound in the face of CHAOS!

A website returning all possible HTTP status codes and code descriptions. For test purposes.

https://github.com/IlianIliev/Status-Codes-Site/blob/master/httpstatuscodes.py

Jan 20, 2012

Mocking

Mock basics

mock = Mock(name='bar', return_value='fish')
mock(1, 2, spam = 99)
# 'fish'
mock.assert_called_once_with(1, 2, spam = 99)
mock.called
# True
mock.call_count
# 1
mock.call_args
# ((1, 2), {'spam': 99})
From: http://blip.tv/pycon-us-videos-2009-2010-2011/pycon-2011-testing-with-mock-4899484

Magic Mock basics

mock = MagicMock()
mock[5]
# <mock.Mock object at 0x2f90690>
mock.__str__.return_value = 'bzzzz'
str(mock)
# 'bzzzz'

Mock exceptions handling test

mock = Mock(side_effect=KeyError('boom'))
mock()
# Traceback (most recent call last)
# ....
# KeyError: 'boom'

Mock file write

>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
...     mock_open.return_value = MagicMock(spec=file)
...
...     with open('/some/path', 'w') as f:
...         f.write('something')
...

>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')
http://stackoverflow.com/questions/1289894/how-do-i-mock-an-open-used-in-a-with-statement-using-the-mock-framework-in-pyth
http://www.voidspace.org.uk/python/mock/magicmock.html

Mock file and raw_post_data

from mock import Mock, MagicMock

class SomeTestCase(TestCase):

    def testRawPostData(self):
        ...

        request = Mock(spec=request)
        request.raw_post_data = 'myrawdata'
        print request.raw_post_data  # prints 'myrawdata'

        file_mock = MagicMock(spec=file)
        file_mock.read.return_value = 'myfiledata'
        request.FILES = {'myfile': file_mock}    
        print request.FILES['myfile'].read()  # prints 'myfiledata'

Mocking stdout

outstream = StringIO()
with patch('sys.stdout', new=outstream) as out:
    ...
    actual_out = out.getvalue()

Video: 
A Gentle Introduction to Mock for Python
Why Use Mock?
Mock and Django

Dec 9, 2011

Экстремальное программирование. Разработка через тестирование

Качество разработанных тестов оценивается методами:
  • Покрытие операторов кода (statement coverage)
  • Намеренное добавление дефекта (defect insertion)
Паттерны разработки основанной на тестах
  • Тест. Отговорка что на тесты нет времени не совсем коректна, так как приложение все равно тестируется, но руками. Но автоматические тесты намного быстрее! Кроме того тесты снижают уровень стресса
  • Изолированный тест (Isolated Test) - основная причина производительность
  • Список тестов (Test List)
  • Вначале тест (Test First)
  • Вначале оператор assert (Assert First)
  • Тестовые данные (Test Data)
  • Понятные данные (Evident Data). Иногда, если данные используются только в одном методе, для лучшей читабельности можно использовать магические числа
Паттерны красной полосы
  • One Test Step
  • Starter Test (Начальный тест)
  • Explanation Test (Объясняющий тест). Тесты могут служить для объяснения кода
  • Learning Test (Тест для обучения)
  • Another Test
  • Regression Test
  • Break
  • Do Over (Начать сначала). Иногда лучше начать заново, чем пытаться довести до ума кривой код
  • Cheap Desk, Nice Chear. Ну, в общем, хорошее кресло решает..
Паттерны тестирования
  • Дочерний тест (Child Test)
  • Mock Object
  • Self Shunt (Самошунтирование). Как можно убедиться что один объект корректно взаимодействует с другим? Можно заставить тестируемый объект взаимодействовать не с целевым объектом, а с тестом.
        def testNotification(self):
            self.count = 0
            result = TestResult()
            result.addListener(self)
            WasRun('testMethod').run(result)
            self.assertEqual(1, self.count)
    
        def startTest(self):
            self.count = self.count + 1
  • Log String (Строка журнал). Полезен когда важен порядок операций. Хорошо сочетается с Self Shunt. Объект-тест реализует методы шунтируемого интерфейса таким образом, что каждый из них добавляет строку в журнал, затем проверяется корректность этих записей.
  • Crush Test Dummy (Тестирование обработки ошибок). Применяется когда надо протестировать как отрабатывает код по обработке ошибки, возникновение которой маловероятно. Для этого создается фэйковый объект который вместо реальной работы генерирует исключение.
  • Broken Test
  • Clean Check-In
Паттерны зеленой полосы
  • Fake It (Подделка)
  • Triangulate
  • Obvious Implemetnation (Очевидная реализация)
  • One To Many (От одного ко многим). Как реализовать работу с коллекцией объектов? Сначала реализуется для одного объекта, затем модернизируется для работы с коллекцией. 
Паттерны xUnit
  • Assertion
  • Fixture
  • External Fixture. Ресурсы освобождаются в tearDown()
  • Test Method
  • Exception Test
  • All Tests

Nov 10, 2011

Setup module function (UnitTest)

The default ordering of tests created by the unittest test loaders is to group all tests from the same modules and classes together. This will lead to setUpClass / setUpModule (etc) being called exactly once per class and module. If you randomize the order, so that tests from different modules and classes are adjacent to each other, then these shared fixture functions may be called multiple times in a single test run.
import unittest

def setUpModule():
    print 'Module setup...'

def tearDownModule():
    print 'Module teardown...'

class Test(unittest.TestCase):
    def setUp(self):
        print 'Class setup...'

    def tearDown(self):
        print 'Class teardown...'

    def test_one(self):
        print 'One'

    def test_two(self):
        print 'Two'