Survey of Unit-Testing Frameworks. by John Szakmeister and Tim Woods



Similar documents
Python Testing with unittest, nose, pytest

Test Driven Development in Python

Python as a Testing Tool. Chris Withers

Testing Python. Applying Unit Testing, TDD, BDD and Acceptance Testing

Python for Test Automation i. Python for Test Automation

Test Automation Integration with Test Management QAComplete

Advanced Topics: Biopython

CIS 192: Lecture 13 Scientific Computing and Unit Testing

Software Testing with Python

Intro to scientific programming (with Python) Pietro Berkes, Brandeis University

Python and Google App Engine

SpiraTest / SpiraTeam Automated Unit Testing Integration & User Guide Inflectra Corporation

Software Testing. Theory and Practicalities

Profiling, debugging and testing with Python. Jonathan Bollback, Georg Rieckh and Jose Guzman

depl Documentation Release depl contributors

Writing robust scientific code with testing (and Python) Pietro Berkes, Enthought UK

Table of Contents. LESSON: The JUnit Test Tool...1. Subjects...2. Testing What JUnit Provides...4. JUnit Concepts...5

Unit Testing webmethods Integrations using JUnit Practicing TDD for EAI projects

Grinder Webtest Documentation

Dry Dock Documentation

Testing Providers with PyWBEM

Unit Testing JUnit and Clover

TEST AUTOMATION FRAMEWORK

Expert PHP 5 Tools. Proven enterprise development tools and best practices for designing, coding, testing, and deploying PHP applications.

Continuous Delivery on AWS. Version 1.0 DO NOT DISTRIBUTE

SciTools Understand Flavor for Structure 101g

New Tools for Testing Web Applications with Python

Python programming Testing

Unit testing with mock code EuroPython 2004 Stefan Schwarzer p.1/25

Git - Working with Remote Repositories

Unit Testing. and. JUnit

Version Control Your Jenkins Jobs with Jenkins Job Builder

Wrestling with Python Unit testing. Warren Viant

Source Code Management for Continuous Integration and Deployment. Version 1.0 DO NOT DISTRIBUTE

Tuskar UI Documentation

How To Deploy Lync 2010 Client Using SCCM 2012 R2

Approach of Unit testing with the help of JUnit

Development Environment and Tools for Java. Brian Hughes IBM

USER GUIDE. Snow Inventory Client for Unix Version Release date Document date

Unit Testing with zunit

personalkollen fredag 5 juli 13

BASIC SMARTFROG COMPONENTS AUTOMATED SOFTWARE INSTALLATION

MS SQL Express installation and usage with PHMI projects

Unit testing with JUnit and CPPUnit. Krzysztof Pietroszek

CME 193: Introduction to Scientific Python Lecture 8: Unit testing, more modules, wrap up

Microsoft Windows PowerShell v2 For Administrators

IBM WebSphere Application Server Version 7.0

Continuous Integration

Installation Documentation Smartsite ixperion 1.3

Developing tests for the KVM autotest framework

Self-review 9.3 What is PyUnit? PyUnit is the unit testing framework that comes as standard issue with the Python system.

Scheduling in SAS 9.3

Setting up the Oracle Warehouse Builder Project. Topics. Overview. Purpose

latest Release 0.2.6

Web based training for field technicians can be arranged by calling These Documents are required for a successful install:

Unit-testing with JML

DevKey Documentation. Release 0.1. Colm O Connor

SAS Marketing Automation 4.4. Unix Install Instructions for Hot Fix 44MA10

/ Preparing to Manage a VMware Environment Page 1

citools Documentation

Professional Plone 4 Development

Specops Command. Installation Guide

Automated Testing with Python

How to utilize Administration and Monitoring Console (AMC) in your TDI solution

Advanced Testing and Continuous Integration

ShoreTel Active Directory Import Application

PCD Test Tools. These tools provide various test functions for the Power Chain Device Toolkit web services (BACnetWS+).

Braindumps.C questions

Setting Up a CLucene and PostgreSQL Federation

Selenium An Effective Weapon In The Open Source Armory

Unit and Functional Testing for the ios Platform. Christopher M. Judd

Installing GFI MailEssentials

TestManager Administration Guide

Module 11 Setting up Customization Environment

Scheduling in SAS 9.4 Second Edition

DEPLOYING EMC DOCUMENTUM BUSINESS ACTIVITY MONITOR SERVER ON IBM WEBSPHERE APPLICATION SERVER CLUSTER

Smart Cloud Integration Pack. For System Center Operation Manager. v User's Guide

EXTRA. Vulnerability scanners are indispensable both VULNERABILITY SCANNER

FileBench's Multi-Client feature

TESTING WITH JUNIT. Lab 3 : Testing

Developing, Deploying, and Debugging Applications on Windows Embedded Standard 7

c360 Portal Installation Guide

Automated ETL Testing with Py.Test. Kevin A. Smith Senior QA Automation Engineer Cambia Health Solutions

Unit Testing & JUnit

User Migration Tool. Note. Staging Guide for Cisco Unified ICM/Contact Center Enterprise & Hosted Release 9.0(1) 1

Configuring FTP Availability Monitoring With Sentry-go Quick & Plus! monitors

Acronis Backup & Recovery 10 Server for Linux. Update 5. Installation Guide

Using Network Application Development (NAD) with InTouch

SCADA/HMI MOVICON TRAINING COURSE PROGRAM

KonyOne Server Installer - Linux Release Notes

App-V Deploy and Publish

Rake Task Management Essentials

CafePilot has 3 components: the Client, Server and Service Request Monitor (or SRM for short).

Access Instructions for United Stationers ECDB (ecommerce Database) 2.0

RecoveryVault Express Client User Manual

Network Security EDA /2012. Laboratory assignment 4. Revision A/576, :13:02Z

Transcription:

Survey of Unit-Testing Frameworks by John Szakmeister and Tim Woods

Our Background Using Python for 7 years Unit-testing fanatics for 5 years

Agenda Why unit test? Talk about 3 frameworks: unittest nose py.test

Why bother? Confidence! Automation To make failures more obvious To prevent regressions Aids debugging

Commonalities All the frameworks: Follow the xunit mentality Verify via asserts

unittest In the standard library The de-facto standard unit test framework

Writing some tests... Need to subclass TestCase import unittest class TestFoo(unittest.TestCase):

Write some tests... The simple way: test methods start with test Use assertions validate your results

Examples... def testisint(self): self.asserttrue(foo.isint(0)) self.assertfalse(foo.isint("not an int")) def testmakelist(self): self.assertequals([1,2,3], foo.makelist(1, 2, 3)) def testdivide(self): self.assertequals(0, foo.divide(0, 1)) self.assertraises( ZeroDivisionError, foo.divide, 1, 0)

Test Fixtures Useful if test cases need more infrastructure setup() is called before each test method teardown() is called after each test method

Example... def setup(self): #... Any *common* set up required for your # test cases can go here self.db = create_db_connection() def teardown(self): # Clean up the fixture here self.db.close()

Running the Tests... Executing all tests within the file is easy Add this to the file: if name == ' main ': unittest.main() Collects all test cases, and executes them using the default console test runner

Example output On the command line, run: :: PYTHONPATH=. python tests_unittest/test_foo.py... --------------------------------------------------- Ran 4 tests in 0.000s OK

Collecting All Tests... Need a suite to help collect the test cases In each file, do the following: def suite(): testsuite = unittest.testsuite() loader = unittest.testloader() for testcase in [TestFoo, TestFooBar]: testsuite.addtest( loader.loadtestsfromtestcase(testcase)) return testsuite

(cont) Pull all the suites together in the init.py: import unittest import test_foo def collectall(): allsuite = unittest.testsuite(test_foo.suite()) # If you have others, you can add them by # doing: # allsuite.addtest(test_bar.suite()) return allsuite

Finally, run all the tests Need to launch unittest.main(), but this time, tell it how to find the full test suite: #!/usr/bin/env python import unittest import tests_unittest unittest.main( defaulttest='tests_unittest.collectall')

setuptools You can launch your tests via setuptools: from setuptools import setup setup(..., test_suite = 'tests_unittest.collectall' )

Pros It s in the standard library Writing the actual tests is easy

Cons Tedious to collect test suites, especially for a large code base Michael Foord is working on this (check out the discover package) Not as easily extensible as other frameworks Others have done it though. See the testtools project in Launchpad.

Future Improvements unittest is vastly improved in Python 2.7 Test discovery Skipping Expected Failures assertraises using with statement New assert methods, and much more

nose Written by Jason Pellerin

Install nose Available from http:// somethingaboutorange.com/mrl/projects/ nose/ Use easy_install: easy_install nose

Just write tests Finds test files, functions, classes, methods test or Test on a word boundary Customize with regular expression No need to write suites Use package structure to organize tests Add init.py to directory

Write a test Create a file, test_foo.py: from nose.tools import * import foo def test_isint(): assert_true(foo.isint(0))

Use assertions Provided in nose.tools Same asserts as unittest, in PEP 8 style Also provides: ok_ => assert eq_ => assert_equals

Use assertions def test_isint(): assert_true(foo.isint(0)) assert_false(foo.isint("not an int")) def test_makelist(): assert_equals([1,2,3], foo.makelist(1, 2, 3)) def test_divide(): eq_(0, foo.divide(0, 1))

Check exceptions Verify that test function raises exception Use raises decorator: @raises(zerodivisionerror) def test_divide_by_zero(): foo.divide(1, 0)

Test fixtures Use with_setup decorator Can be used for simple setup More complex cases should probably use a test class Fixtures per package, module, class

Test fixtures _db = None def setup_func(): global _db _db = create_db_connection() def teardown_func(): global _db _db.close() @with_setup(setup_func, teardown_func) def test_with_fixture(): ok_(isinstance(_db, DummyConnection))

Test classes Define class that matches test regexp Define test methods in the class Optionally define setup and teardown

Test classes class TestFoo(): def setup(self): # Fixture setup self.db = create_db_connection() def teardown(self): # Fixture teardown self.db.close() def test_isint(self): ok_(foo.isint(0)) def test_dbconn(self): ok_(isinstance(self.db, DummyConnection))

Generative tests Each yield results in a test case def test_generator(): for i in xrange(0, 20, 2): yield check_even, i def check_even(even_number): assert_true(foo.iseven(even_number)) assert_false(foo.iseven(even_number + 1))

Attributes Add attribute tag to tests from nose.plugins.attrib import attr @attr('nothing') def test_zero_equals_zero(): assert 0 == 0 Can set a specific value @attr(speed= slow )

Attributes Select attributes at runtime (-a/--attr) nothing speed=slow Python expression (-A/--eval-attr) not nothing (speed== slow and not nothing)

Skip tests Raise exception to report test skipped from nose.plugins.skip import SkipTest def test_skipme(): raise SkipTest

Runs unittest tests Loads tests from unittest.testcase subclasses Easily used as a front-end for legacy tests

Running tests Type nosetests at the top level Run a subset of tests cd package; nosetests nosetests package/tests/module.py nosetests package.tests.module:name

Other features setuptools integration Plugin system Debug, code coverage and profiling Doctest runner XUnit XML output

Pros No tedious mucking about with suites Can be used with legacy unittest tests Generative tests Plugins

Cons Not in standard library No official release supporting Python 3.x py3k branch exists

py.test Written by Holger Krekel

Install py.test Actually part of pylib Download from http://pytest.org/ Use easy_install: easy_install py

Easy to get started.. Just create a test file Make sure it starts with test_ Start adding test methods, or test classes: import foo import py.test def test_isint(): pass

Uses assert def test_isint(): assert True == foo.isint(0) assert False == foo.isint("not an int") def test_makelist(): assert [1,2,3] == foo.makelist(1, 2, 3)

Checking exceptions... Use py.test.raises() def test_divide(): assert 0 == foo.divide(0, 1) # Dividing 1 by 0 should raise # ZeroDivisionError py.test.raises( ZeroDivisionError, foo.divide, 1, 0)

Test classes Just start the class with Test : class TestFoo(): def test_isint(self): assert True == foo.isint(0) assert False == foo.isint("not an int")

Test Fixtures With test classes, use: def setup_method(self, method): # Fixture setup self.db = create_db_connection() def teardown_method(self, method): # Fixture teardown self.db.close()

Funcargs Helps you to create arguments instead def pytest_funcarg db(request): db = create_db_connection() request.addfinalizer(lambda: db.close()) return db def test_db(db): #... do something assert isinstance(db, DummyConnection) Funcargs are the preferred way in py.test

Funcargs Helps you to create arguments instead def pytest_funcarg db(request): db = create_db_connection() request.addfinalizer(lambda: db.close()) return db def test_db(db): #... do something assert isinstance(db, DummyConnection) Funcargs are the preferred way in py.test

Generative tests... Similar to nose def test_generative(): for i in xrange(0,20,2): yield check_even, i def check_even(even_number): assert True == foo.iseven(even_number) assert False == foo.iseven(even_number+1) This has been deprecated though

Generative tests... New style test generators Still experimental Encompasses several ways of doing: Parameterized tests Scenario tests

Marking tests... Can mark tests as expected failure @py.test.mark.xfail def test_xfail(): assert 0 == 1 Or with keywords # A test marked with keyword "nothing" @py.test.mark(nothing=true) def test_zero_equals_zero(): assert 0 == 0

Marking tests... Some keywords are added automatically Filename Class names Function names

Skipping Tests Skip if an import fails bogus = py.test.importorskip("bogus") Skip all when done at module level Skips an individual test when done inside a test function Skip for some other reason py.test.skip("a short message")

Disabling a test class Great for disabling platform-specific tests: class TestWin32Only: disabled = sys.platform!= 'win32' # Test cases follow Also good for disabling tests that require a specific software/hardware setup Need a decent way to test for it Keywords are useful for this too

Executing Tests Use the py.test command: py.test [/path/to/file/or/dir] [ ] Automatically collects tests Begins executing tests immediately

Executing Tests Tests with a specific keyword: py.test -k keyword Tests that don t have a specific keyword: py.test -k -keyword

Distributed Testing Two modes Local Remote

Locally Take advantage of multiprocessors machine Significant speedups if tests are IO bound To run tests in <num> processes, use: py.test -n <num>

Remotely Two strategies Load balancing - every test one run once py.test --dist=load py.test -d Multiplatform - run every test on each platform py.test --dist=each

Remote Mechanisms Use ssh py.test -d --tx ssh=user@host//chdir=/tmp \ --rsyncdir pkg Use a gateway py.test -d --tx socket=ip:port//chdir=/tmp \ --rsyncdir pkg Gateway launched via a small script Does not require installing pylib

conftest.py Captures command-line args in a config file Great for storing remote test configuration pytest_option_tx = ["ssh=localhost"] pytest_option_dist="load" # Paths are relative to conftest.py rsyncdirs = [".", "../foo.py"] Can also configure plugin options

Other features Can drop into PDB on error Has a plugin system Execute unittest-style TestCases Coverage reporting (via figleaf) Pylint integration And many more

Pros Don t need to collect the tests Generative tests Marking tests Distributed testing Excels with large test suites More to py.test than this small example

Cons Default output is a bit sloppy Funcargs and generative == breakage! No Python 3 support yet Distributed tests can hang on an internal failure

We have source! http://www.szakmeister.net/misc/unit-testing.zip

Questions?