updated Oct 27, 2019
Python unit testing: call the same test method with parameters by data
decorator
Common situation: we want to cover many similar test cases that differ in one or several variables values only (input test data, results etc), without code duplication.
Tests with one data value
The test method should be without parameters, but we could place the code called several times into a separate function and call it from the test method:
class TestPrice(TestCase): def test_positive(self): check_price_valid(10) check_price_valid(0.99) def check_price_valid(self, price): result = PriceValidator().check(price) self.assertTrue(result)But there's still extra method there. There's another way to do the same but with the less code:
from ddt import ddt, data @ddt class TestPrice(TestCase): @data(10, 0.99) def test_positive(self, price): result = PriceValidator().check(price) self.assertTrue(result)How it works:
ddt
test class decorator creates several test methods instead each test method with the data
decorator: as many as quantity of the data
decorator parameters. So test_positive
method in the example above is replaced with two methods: their names consist from the original method name and the parameter values string suffix.
Tests with many data values
Let's assume we want something like this:class TestPrice(TestCase): def test_price_valid(self): check_price_valid(10, True) check_price_valid(0, False) def check_price_valid(self, price, expected_result): result = PriceValidator().check(price) self.assertEquals(expected_result, result)We could rewrite with
data
decorator like this:
from ddt import ddt, data @ddt class TestPrice(TestCase): @data((10, True), (0, False)) def test_price_valid(self, test_data): price, expected_result = test_data result = PriceValidator().check(price) self.assertEquals(expected_result, result)or even better, changing the test method signature to many arguments with
unpack
decorator so it's clear from the method parameters what's the test data it depends on:
from ddt import ddt, data, unpack @ddt class TestPrice(TestCase): @data((10, True), (0, False)) @unpack def test_price_valid(self, price, expected_result): result = PriceValidator().check(price) self.assertEquals(expected_result, result)