Data-Driven Tests for Python Unittest

Related tags

Testingddt
Overview

Run Tests codecov.io
Version Downloads

DDT (Data-Driven Tests) allows you to multiply one test case by running it with different test data, and make it appear as multiple test cases.

Installation

pip install ddt

Check out the documentation for more details.

See Contributing if you plan to contribute to ddt, and License if you plan to use it.

Comments
  • Add basic support for YAML data files

    Add basic support for YAML data files

    Add support for YAML files, when PyYAML is installed. If PyYAML is not installed, any YAML file_data functions error out.

    Only files ending with .yml or .yaml are considered to be YAML files. All other files are loaded as JSON files.

    opened by pradyunsg 16
  • Do not allow dots on test names

    Do not allow dots on test names

    Dots is not allowed on function/methods names, so the names generated for ddt should not allow dots on the generated name.

    This pull request ensure that there are no dots on ddt generated function/method names.

    opened by elyezer 15
  • Brainstorming: What do you want in ddt v2.0.0?

    Brainstorming: What do you want in ddt v2.0.0?

    I noticed that @txels had expressed the desire to ditch backwards compatibility and give ddt another shot to get a more powerful platform on the other side. Hence, with the intent of sparking discussion, I write this.

    opened by pradyunsg 14
  • Looking for a project maintainer

    Looking for a project maintainer

    I am officially dropping support for ddt. It's had its time, but now that I've transitioned to using py.test in my projects, it brings me no value and no longer use it.

    If you however still see value in it and would like to step up as a maintainer, let me know and we'll manage a transfer of ownership.

    Please comment on this issue if you're interested.

    help-wanted 
    opened by txels 12
  • Using dicts as @data generates variable test names

    Using dicts as @data generates variable test names

    Here's a simple test case:

    import unittest
    from ddt import ddt, data
    
    @ddt
    class Test(unittest.TestCase):
        @data(1)
        def test_scalar(self, value):
            pass
    
        @data({"a": 1, "b": 2})
        def test_dict(self, value):
            pass
    

    When run with python3.4which nosetests-v test.py you'll get (potentially) different test names with different runs:

    $ nosetests -V
    nosetests version 1.3.1
    $ python3.4 `which nosetests` -v test.py
    test_dict_1___b___2___a___1_ (test.Test) ... ok
    test_scalar_1_1 (test.Test) ... ok
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    $ python3.4 `which nosetests` -v test.py
    test_dict_1___a___1___b___2_ (test.Test) ... ok
    test_scalar_1_1 (test.Test) ... ok
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    

    Why this is a problem:

    • It breaks nosetest's TestId functionality (e.g. makes running nosetests --with-ids --failed fail). Being able to re-run failed tests only (--failed) is a super-useful feature, so it not working is a big problem (time-waster).

    The reason why this happens is that from Python 3.3 onwards hash randomization has been the default option (see https://docs.python.org/3.3/using/cmdline.html#cmdoption-R). This means that dict key hashes (at least for types with hash function depending on the system hash()) change from different runs, and thus the naming of tests using @data with dicts (or sets/frozensets for that matter) will vary from one run to another.

    Although there is a simple workaround (use a fixed PYTHONHASHSEED when running tests) this is still not a completely good solution for a few reasons:

    • This is going to bite a lot of people not familiar with hash randomization.
    • This is going to bite those who move from older pythons to 3.3 or newer versions.

    On the other hand I am not sure how to fix this. A few possibilities:

    1. Update mk_test_name to recognize dicts (and sets and frozensets and recursive versions of these) and output keys in known (sorted) order.
    2. Add a check that will produce a visible WARNING message when it detects running in post-3.3 python without PYTHONHASHSEED being set.
    3. Add a check that will make mk_test_name omit the str(value) bit on >= 3.3 python if PYTHONHASHSEED hasn't been set. This would generate test names based only the running index, keeping them unique and immune to hash key randomization.

    (And in any case add a note about this behavior to @data documentation.)

    I think the first one is a can of worms since you'd need to handle recursive dicts and it really does not help with complex types that are not dicts but internally use dicts and produce str values from those.

    The second one would help, but would essentially require changes to test environment when moving to >= 3.3 python on existing projects, and the warning might also be missed by a lot of people.

    I think the third one would present the least surprise to people as it'd at least keep test cases accessible and running, yet makes it possible to get the full name (with test data str-encoded) by introducing PYTHONHASHSEED to the test environment by the user.

    Comments, thoughts?

    opened by santtu 11
  • Allow index-only test names

    Allow index-only test names

    What: I would like to add a feature to ddt so that test names can be generated using just the index only.

    How: To allow that to happen, I am making use of kwargs at the class-level decorator @ddt. When decorating a class with @ddt(formatTestName=FormatTestName.INDEX_ONLY), the boolean value will be passed to mk_test_name() and test names will just be index-only.

    Why: An easier way to trigger a specific test to run.

    Testing: New unit test added. Using tox to run against py27 and py35.

    GLOB sdist-make: /path/masked/ddt/setup.py
    py27 inst-nodeps: /path/masked/ddt/.tox/.tmp/package/1/ddt-1.3.1.zip
    py27 installed: DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support,alabaster==0.7.12,Babel==2.8.0,certifi==2020.4.5.1,chardet==3.0.4,configparser==4.0.2,coverage==5.1,ddt==1.3.1,docutils==0.16,entrypoints==0.3,enum34==1.1.10,flake8==3.7.9,funcsigs==1.0.2,functools32==3.2.3.post2,idna==2.9,imagesize==1.2.0,Jinja2==2.11.2,MarkupSafe==1.1.1,mccabe==0.6.1,mock==3.0.5,nose==1.3.7,packaging==20.3,pycodestyle==2.5.0,pyflakes==2.1.1,Pygments==2.5.2,pyparsing==2.4.7,pytz==2019.3,PyYAML==5.3.1,requests==2.23.0,six==1.14.0,snowballstemmer==2.0.0,Sphinx==1.8.5,sphinxcontrib-programoutput==0.16,sphinxcontrib-websupport==1.1.2,typing==3.7.4.1,urllib3==1.25.8
    py27 run-test-pre: PYTHONHASHSEED='2507378467'
    py27 run-test: commands[0] | nosetests -s --with-coverage --cover-package=ddt --cover-html
    .................................................................................
    Name     Stmts   Miss  Cover
    ----------------------------
    ddt.py     131      0   100%
    ----------------------------------------------------------------------
    Ran 81 tests in 0.092s
    
    OK
    py27 run-test: commands[1] | flake8 ddt.py test
    py27 run-test: commands[2] | sphinx-build -b html docs docs/_build
    Running Sphinx v1.8.5
    loading pickled environment... done
    building [mo]: targets for 0 po files that are out of date
    building [html]: targets for 0 source files that are out of date
    updating environment: [] 0 added, 1 changed, 0 removed
    reading sources... [100%] example
    
    /path/masked/ddt/docs/example.rst:29: WARNING: Include file u'/path/masked/ddt/test/test_data_dict_dict.json' not found or reading it failed
    /path/masked/ddt/docs/example.rst:34: WARNING: Include file u'/path/masked/ddt/test/test_data_dict_dict.yaml' not found or reading it failed
    /path/masked/ddt/docs/example.rst:39: WARNING: Include file u'/path/masked/ddt/test/test_data_dict.json' not found or reading it failed
    /path/masked/ddt/docs/example.rst:44: WARNING: Include file u'/path/masked/ddt/test/test_data_dict.yaml' not found or reading it failed
    /path/masked/ddt/docs/example.rst:49: WARNING: Include file u'/path/masked/ddt/test/test_data_list.json' not found or reading it failed
    /path/masked/ddt/docs/example.rst:54: WARNING: Include file u'/path/masked/ddt/test/test_data_list.yaml' not found or reading it failed
    looking for now-outdated files... none found
    pickling environment... done
    checking consistency... done
    preparing documents... done
    writing output... [ 50%] example
    writing output... [100%] index
    
    generating indices... genindex py-modindex
    writing additional pages... search
    copying static files... WARNING: html_static_path entry u'/path/masked/ddt/docs/_static' does not exist
    done
    copying extra files... done
    dumping search index in English (code: en) ... done
    dumping object inventory... done
    build succeeded, 7 warnings.
    
    The HTML pages are in docs/_build.
    py35 inst-nodeps: /path/masked/ddt/.tox/.tmp/package/1/ddt-1.3.1.zip
    py35 installed: coverage==5.1,ddt==1.3.1,entrypoints==0.3,flake8==3.7.9,mccabe==0.6.1,nose==1.3.7,pycodestyle==2.5.0,pyflakes==2.1.1,PyYAML==5.3.1,six==1.14.0
    py35 run-test-pre: PYTHONHASHSEED='2507378467'
    py35 run-test: commands[0] | nosetests -s --with-coverage --cover-package=ddt --cover-html
    .................................................................................
    Name     Stmts   Miss  Cover
    ----------------------------
    ddt.py     131      0   100%
    ----------------------------------------------------------------------
    Ran 81 tests in 0.099s
    
    OK
    py35 run-test: commands[1] | flake8 ddt.py test
    ___________________________________________________________________________ summary ____________________________________________________________________________
      py27: commands succeeded
      py35: commands succeeded
      congratulations :)
    
    feature request 
    opened by zorchan 10
  • New decorator to retrieve test data from JSON files

    New decorator to retrieve test data from JSON files

    Hi @txels

    I've added a new decorator file_data that will load test data from a JSON file.

    At the moment the JSON file can only contain a flat list of values but if you like this idea/approach I can add support to a schema like the following

    [
     { 'test_name':  [1, 2, 5, 6],
       'test_name_2': [10, 33, 5]
     }
     ...
    ]
    

    This would create 4 tests with the test_name appended to the original test function name (or even replaced but this might be confusing) and 3 more tests with test_name_2 appended to the name.

    opened by bulkan 10
  • Add `@idata(iterable)` decorator-function.

    Add `@idata(iterable)` decorator-function.

    The purpose is to replace the construct below:

    @data(*[a for a in foo if a > 0])
    

    With this typing & memory-efficient alternative:

    @data(a for a in foo if a > 0)
    

    (*) It is a minor change that should not interfere with the possible re-write of the library in other branches.

    opened by ankostis 9
  • Breaking behavior in latest release (1.0.1)

    Breaking behavior in latest release (1.0.1)

    A change in the latest release of ddt (#22 included in 1.0.1) has seemingly introduced breaking behavior for wrapped tests expecting a dictionary object when receiving test data, as exemplified below:

    test_data.json

    {
      "test_name": {
        "arg_one": "test1",
        "arg_two": "test2",
        "arg_three": "test3"
      }
    }
    

    Original test code:

    @ddt.file_data('test_data.json')
    def test_something(inputs):
        arg_one = inputs["arg_one"]
        arg_two = inputs["arg_two"]
        arg_three = inputs["arg_three"]
        # Perform tests here
        pass
    

    New test code:

    @ddt.file_data('test_data.json')
    def test_something(arg_one, arg_two, arg_three):
        # Perform tests here
        pass
    

    Since this behavior appears to be non-configurable and backward-incompatible, this seems more like a major version change rather than a simple patch. Can this change be reverted at least for the time being?

    opened by Kuwagata 9
  • Allow unpacking test data tuples into multiple arguments to the test case

    Allow unpacking test data tuples into multiple arguments to the test case

    Right now, if you want to pass several arguments to your test, you typically provide a tuple for each test case, and have to unpack them inside the test method, such as:

    @data((1,2,3), (4,5,9))
    def test_things_with_3_numbers(self, arg):
        op1, op2, addition = arg
        ...
    

    A nice improvement could be if ddt did this unpacking for you:

    @packed_data((1,2,3), (4,5,9))
    def test_things_with_3_numbers(self, op1, op2, addition):
        ...
    
    opened by txels 9
  • Simple enhancement to @ddt decorator to make it possible to provide user-friendly test method names

    Simple enhancement to @ddt decorator to make it possible to provide user-friendly test method names

    Basically, this allows to do something like:

    def make_data(...):
        d = ...
        setattr(d, "__name__", "friendly_name_computed_from_data")
        return d
    
    @dds
    class ...:
        @data(make_data(...), make_data(....), make_data(...))
        def test_much_data(self, data):
            ....
    

    Unless __name__ is in the data, the current formatting behavior is used.

    opened by santtu 8
  • Remove python-six dependency

    Remove python-six dependency

    The python-six dependency is only used to detect python version in one test. This patch uses the pytest.mark.skipif to split that test in two and skip dependending on python version.

    opened by danigm 0
  • Allow `named_data` to take tuples (any `collections.Sequence`)

    Allow `named_data` to take tuples (any `collections.Sequence`)

    @named_data currently explicitly checks for lists or dicts, but in the case of lists it could just check against sequences (including tuples) and work in exactly the same way.

    opened by orgadish 0
  • @ifile_data - an iterable @file_data decorator

    @ifile_data - an iterable @file_data decorator

    tldr; a combination of the @idata and @file_data decorators

    Use Case

    Add a decorator @ifile_data to pass multiple files as data items into a test function.

    1. Files would be specified by a glob pattern relative to the test files directory.

    2. The name of the test case would be the file.name of each file.

    3. Test generated test names should include the file name.

    MyTest_0_some_1234_json MyTest_1_some_xyz_json

    an example of how this operator would be used.

    @ddt
    class MyTestCase(unittest.TestCase):
    
      @ifile_data('./data/some_*.json')
      def MyTest(self, some_data):
        self.assertIsNotNone(some_data)
    
    

    workaround

    I am using this as a workaround for now:

    from unittest import TestCase, mock
    import json
    from ddt import ddt, idata
    from pathlib import Path
    
    
    class NamedList(list):
        pass
    
    
    def get_file_data(glob_pattern):
    
        result = []
    
        for file in Path(__file__).parent.glob(glob_pattern):
            with open(file) as reader:
                dataitem = NamedList(json.load(reader))
                setattr(dataitem, '__name__', file.name)
                result.append(dataitem)
    
        return result
    
    
    @ddt
    class FileDataTests(TestCase):
        @idata(get_file_data('./data/some_*.json'))
        def test_file_data(self, some_data):
            self.assertIsNotNone(some_data)
    
    opened by jasonchester 1
  • run specific tests from cli

    run specific tests from cli

    With unittest it is possible to run specific tests from the cli. When using ddt this doesn't seem to be possible.

    Example:

    import unittest
    from ddt import data, ddt
    
    
    class Test(unittest.TestCase):
        def test(self):
            self.assertEqual(1, 1)
    
    @ddt
    class TestDDT(unittest.TestCase):
        @data('arg1', 'arg2')
        def test(self, arg='arg1'):
            self.assertEqual(1, 1)
    
    if __name__ == '__main__':
        unittest.main(exit=False)
    

    Running specific unittest:

    $  python test.py Test.test
    .
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    
    OK
    

    Running specific unittest with ddt:

    $ python test.py TestDDT.test
    E
    ======================================================================
    ERROR: test (unittest.loader._FailedTest)
    ----------------------------------------------------------------------
    AttributeError: type object 'TestDDT' has no attribute 'test'
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.000s
    
    FAILED (errors=1)
    
    feature request 
    opened by tadly 6
Releases(1.6.0)
  • 1.6.0(Aug 10, 2022)

    What's Changed

    • Moved @named_data into main ddt.py module so it can be imported. by @orgadish in https://github.com/datadriventests/ddt/pull/109
    • Enable usage of Sequence in named_data.py by @orgadish in https://github.com/datadriventests/ddt/pull/108

    Full Changelog: https://github.com/datadriventests/ddt/compare/1.5.0...1.6.0

    Source code(tar.gz)
    Source code(zip)
  • 1.5.0(May 24, 2022)

    What's Changed

    • @named_data decorator to give tests with @data custom names by @orgadish in https://github.com/datadriventests/ddt/pull/103
    • End support for 3.5 by @wswld in https://github.com/datadriventests/ddt/pull/104
    • Add new Python versions support by @wswld in https://github.com/datadriventests/ddt/pull/105

    New Contributors

    • @orgadish made their first contribution in https://github.com/datadriventests/ddt/pull/103

    Full Changelog: https://github.com/datadriventests/ddt/compare/1.4.4...1.5.0

    Source code(tar.gz)
    Source code(zip)
  • 1.4.4(Oct 4, 2021)

  • 1.4.3(Sep 27, 2021)

  • 1.4.2(Mar 12, 2021)

  • 1.4.1(May 15, 2020)

  • 1.4.0(May 7, 2020)

  • 1.3.1(Mar 18, 2020)

  • 1.3.0(Mar 10, 2020)

  • 1.2.2(Dec 2, 2019)

  • 1.2.1(Feb 24, 2019)

  • 1.2.0(Jul 17, 2018)

  • 1.1.3(May 13, 2018)

  • 1.1.1(Oct 7, 2016)

    Changes since 1.1.0:

    7198dfb Merge pull request #45 from nedbat/master 969c915 Merge pull request #40 from ankostis/iterable_data 2d0a689 Merge pull request #43 from pradyunsg/patch-1

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Oct 7, 2016)

  • 1.0.3(Oct 7, 2016)

  • 1.0.2(Oct 7, 2016)

  • 1.0.1(Oct 7, 2016)

    Changes since 1.0.0:

    9fcc499 Merge pull request #36 from redixin/fix_mock_testr 57c1b23 Merge pull request #34 from carlgeorge/six-minimum-version 7ed3a52 Merge pull request #22 from garymacindoe/master 7ca1ad2 Merge pull request #33 from domidimi/master 9e9998b Merge pull request #26 from stevepeak/master ef48408 Merge pull request #28 from mycharis/mycharis-fix-tox-ini 2ac5054 Merge branch 'master' of github.com:txels/ddt

    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Oct 7, 2016)

  • 0.8.1(Oct 7, 2016)

  • 0.8.0(Oct 7, 2016)

  • 0.7.1(Oct 7, 2016)

Mypy static type checker plugin for Pytest

pytest-mypy Mypy static type checker plugin for pytest Features Runs the mypy static type checker on your source files as part of your pytest test run

Dan Bader 218 Jan 03, 2023
splinter - python test framework for web applications

splinter - python tool for testing web applications splinter is an open source tool for testing web applications using Python. It lets you automate br

Cobra Team 2.6k Dec 27, 2022
AutoExploitSwagger is an automated API security testing exploit tool that can be combined with xray, BurpSuite and other scanners.

AutoExploitSwagger is an automated API security testing exploit tool that can be combined with xray, BurpSuite and other scanners.

6 Jan 28, 2022
py.test fixture for benchmarking code

Overview docs tests package A pytest fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. See c

Ionel Cristian Mărieș 1k Jan 03, 2023
Sixpack is a language-agnostic a/b-testing framework

Sixpack Sixpack is a framework to enable A/B testing across multiple programming languages. It does this by exposing a simple API for client libraries

1.7k Dec 24, 2022
Docker-based integration tests

Docker-based integration tests Description Simple pytest fixtures that help you write integration tests with Docker and docker-compose. Specify all ne

Avast 326 Dec 27, 2022
Tools for test driven data-wrangling and data validation.

datatest: Test driven data-wrangling and data validation Datatest helps to speed up and formalize data-wrangling and data validation tasks. It impleme

269 Dec 16, 2022
A Python Selenium library inspired by the Testing Library

Selenium Testing Library Slenium Testing Library (STL) is a Python library for Selenium inspired by Testing-Library. Dependencies Python 3.6, 3.7, 3.8

Anže Pečar 12 Dec 26, 2022
Codeforces Test Parser for C/C++ & Python on Windows

Codeforces Test Parser for C/C++ & Python on Windows Installation Run pip instal

Minh Vu 2 Jan 05, 2022
A modern API testing tool for web applications built with Open API and GraphQL specifications.

Schemathesis Schemathesis is a modern API testing tool for web applications built with Open API and GraphQL specifications. It reads the application s

Schemathesis.io 1.6k Dec 30, 2022
1st Solution to QQ Browser 2021 AIAC Track 2

1st Solution to QQ Browser 2021 AIAC Track 2 This repository is the winning solution to QQ Browser 2021 AI Algorithm Competition Track 2 Automated Hyp

DAIR Lab 24 Sep 10, 2022
HTTP client mocking tool for Python - inspired by Fakeweb for Ruby

HTTPretty 1.0.5 HTTP Client mocking tool for Python created by Gabriel Falcão . It provides a full fake TCP socket module. Inspired by FakeWeb Github

Gabriel Falcão 2k Jan 06, 2023
Useful additions to Django's default TestCase

django-test-plus Useful additions to Django's default TestCase from REVSYS Rationale Let's face it, writing tests isn't always fun. Part of the reason

REVSYS 546 Dec 22, 2022
Percy visual testing for Python Selenium

percy-selenium-python Percy visual testing for Python Selenium. Installation npm install @percy/cli: $ npm install --save-dev @percy/cli pip install P

Percy 9 Mar 24, 2022
pytest plugin for a better developer experience when working with the PyTorch test suite

pytest-pytorch What is it? pytest-pytorch is a lightweight pytest-plugin that enhances the developer experience when working with the PyTorch test sui

Quansight 39 Nov 18, 2022
Python Webscraping using Selenium

Web Scraping with Python and Selenium The code shows how to do web scraping using Python and Selenium. We use as data the https://sbot.org.br/localize

Luís Miguel Massih Pereira 1 Dec 01, 2021
A Django plugin for pytest.

Welcome to pytest-django! pytest-django allows you to test your Django project/applications with the pytest testing tool. Quick start / tutorial Chang

pytest-dev 1.1k Dec 31, 2022
Selenium Page Object Model with Python

Page-object-model (POM) is a pattern that you can apply it to develop efficient automation framework.

Mohammad Ifran Uddin 1 Nov 29, 2021
Browser reload with uvicorn

uvicorn-browser This project is inspired by autoreload. Installation pip install uvicorn-browser Usage Run uvicorn-browser --help to see all options.

Marcelo Trylesinski 64 Dec 17, 2022