[Python-Dev] PEP: Consolidating names and classes in the `unittest` module

Ben Finney ben+python at benfinney.id.au
Mon Jul 14 15:25:32 CEST 2008


:PEP:           XXX
:Title:         Consolidating names and classes in the `unittest` module
:Version:       0.0
:Last-Modified: 2008-07-14
:Author:        Ben Finney <ben+python at benfinney.id.au>
:Status:        Draft
:Type:          Standards Track
:Content-Type:  test/x-rst
:Created:       2008-07-14
:Post-History:


..  contents::


Abstract
========

This PEP proposes to consolidate the names and classes that constitute
the API of the standard library `unittest` module, with the goal of
removing redundant names, conforming with PEP 8, and eliminating
classic classes.


Motivation
==========

The normal use case for the `unittest` module is to subclass its
classes, overriding and re-using its functios and methods. This draws
constant attention to the fact that the existing implementation fails
several current Python standards:

* It does not use new-style classes, preventing e.g. straightforward
  use of ``super`` for calling the fixture set-up and tear-down
  methods.

* It does not conform to PEP 8, requiring users to write their own
  non-PEP-8 conformant names when overriding methods, and encouraging
  extensions to further depart from PEP 8.

* It has many synonyms in its API, which goes against the Zen of
  Python (specifically, that "there should be one, and preferably only
  one, obvious way to do it").


Specification
=============

Use new-style classes throughout
--------------------------------

The following classes will inherit explicitly from the built-in
`object` type, to make all classes in the module part of the new-style
type hierarchy.

* ``TestResult``
* ``TestCase``
* ``TestSuite``
* ``TestLoader``
* ``_WritelnDecorator``
* ``TextTestRunner``
* ``TestProgram``

Remove obsolete names
---------------------

The following attributes are not documented as part of the API and are
marked as obsolete in the implementation. They will be removed.

* ``_makeLoader``
* ``getTestCaseNames``
* ``makeSuite``
* ``findTestCases``

Remove redundant names
----------------------

The following attribute names exist only as synonyms for other names.
They are to be removed, leaving only one name for each attribute in
the API.

``TestCase`` attributes
~~~~~~~~~~~~~~~~~~~~~~~

* ``assertEqual``
* ``assertEquals``
* ``assertNotEqual``
* ``assertNotEquals``
* ``assertAlmostEqual``
* ``assertAlmostEquals``
* ``assertNotAlmostEqual``
* ``assertNotAlmostEquals``
* ``assertRaises``
* ``assert_``
* ``assertTrue``
* ``assertFalse``

Conform API with PEP 8
----------------------

The following names are to be introduced, each replacing an existing
name, to make all names in the module conform with PEP 8. Each name is
shown with the existing name that it replaces.

Where function parameters are to be renamed also, they are shown.
Where function parameters are not to be renamed, they are elided with
the ellipse ("…") symbol.

Module attributes
~~~~~~~~~~~~~~~~~

``_make_loader(prefix, sort_using, suite_class)``
  Replaces ``_makeLoader (prefix, sortUsing, suiteClass)``

``find_test_cases(module, prefix, sort_using, suite_class)``
  Replaces ``findTestCases(module, prefix, sortUsing, suiteClass)``

``get_test_case_names(test_case_class, prefix, sort_using)``
  Replaces ``getTestCaseNames(testCaseClass, prefix, sortUsing)``

``make_suite(test_case_class, prefix, sort_using, suite_class)``
  Replaces ``makeSuite(testCaseClass, prefix, sortUsing, suiteClass)``

``default_test_loader``
  Replaces ``defaultTestLoader``

``TestResult`` atributes
~~~~~~~~~~~~~~~~~~~~~~~~

``add_error(…)``
  Replaces ``addError(…)``

``add_result(…)``
  Replaces ``addResult(…)``

``add_success(…)``
  Replaces ``addSuccess(…)``

``should_stop``
  Replaces ``shouldStop``

``start_test(…)``
  Replaces ``startTest(…)``

``stop_test(…)``
  Replaces ``stopTest(…)``

``tests_run``
  Replaces ``testsRun``

``was_successful(…)``
  Replaces ``wasSuccessful(…)``

``TestCase`` attributes
~~~~~~~~~~~~~~~~~~~~~~~

``__init__(self, method_name='run_test')``
  Replaces ``__init__(self, methodName='runTest')``

``_test_method_doc``
  Replaces ``_testMethodDoc``

``_test_method_name``
  Replaces ``_testMethodName``

``failure_exception``
  Replaces ``failureException``

``count_test_cases(…)``
  Replaces ``countTestCases(…)``

``default_test_result(…)``
  Replaces ``defaultTestResult(…)``

``fail_if(…)``
  Replaces ``failIf(…)``

``fail_if_almost_equal(…)``
  Replaces ``failIfAlmostEqual(…)``

``fail_if_equal(…)``
  Replaces ``failIfEqual(…)``

``fail_unless(…)``
  Replaces ``failUnless(…)``

``fail_unless_almost_equal(…)`` 
  Replaces ``failUnlessAlmostEqual(…)``

``fail_unless_equal(…)``
  Replaces ``failUnlessEqual(…)``

``fail_unless_raises(exc_class, callable_obj, *args, **kwargs)``
  Replaces ``failUnlessRaises(excClass, callableObj, *args, **kwargs)``

``run_test(…)``
  Replaces ``runTest(…)``

``set_up(…)``
  Replaces ``setUp(…)``

``short_description(…)``
  Replaces ``shortDescription(…)``

``tear_down(…)``
  Replaces ``tearDown(…)``

``FunctionTestCase`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``__init__(self, test_func, set_up, tear_down, description)``
  Replaces ``__init__(self, testFunc, setUp, tearDown, description)``

``run_test(…)``
  Replaces ``runTest(…)``

``set_up(…)``
  Replaces ``setUp(…)``

``short_description(…)``
  Replaces ``shortDescription(…)``

``tear_down(…)``
  Replaces ``tearDown(…)``

``TestSuite`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~

``add_test(…)``
  Replaces ``addTest(…)``

``add_tests(…)``
  Replaces ``addTests(…)``

``count_test_cases(…)``
  Replaces ``countTestCases(…)``

``TestLoader`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~~

``sort_test_methods_using``
  Replaces ``sortTestMethodsUsing``

``suite_class``
  Replaces ``suiteClass``

``test_method_prefix``
  Replaces ``testMethodPrefix``

``get_test_case_names(self, test_case_class)``
  Replaces ``getTestCaseNames(self, testCaseClass)``

``load_tests_from_module(…)``
  Replaces ``loadTestsFromModule(…)``

``load_tests_from_name(…)``
  Replaces ``loadTestsFromName(…)``

``load_tests_from_names(…)``
  Replaces ``loadTestsFromNames(…)``

``load_tests_from_test_case(self, test_case_class)``
  Replaces ``loadTestsFromTestCase(self, testCaseClass)``

``_TextTestResult`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``show_all``
  Replaces ``showAll``

``add_error(…)``
  Replaces ``addError(…)``

``add_failure(…)``
  Replaces ``addFailure(…)``

``add_success(…)``
  Replaces ``addSuccess(…)``

``get_description(…)``
  Replaces ``getDescription(…)``

``print_error_list(…)``
  Replaces ``printErrorList(…)``

``print_errors(…)``
  Replaces ``printErrors(…)``

``start_test(…)``
  Replaces ``startTest(…)``

``TextTestRunner`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``_make_result(…)``
  Replaces ``_makeResult(…)``

``TestProgram`` attributes
~~~~~~~~~~~~~~~~~~~~~~~~~~

``__init__(self, module, default_test, argv, test_runner, test_loader)``
  Replaces ``__init__(self, module, defaultTest, argv, testRunner, testLoader)``

``create_tests(…)``
  Replaces ``createTests(…)``

``parse_args(…)``
  Replaces ``parseArgs(…)``

``run_tests(…)``
  Replaces ``runTests(…)``

``usage_exit(…)``
  Replaces ``usageExit(…)``


Rationale
=========

New-style classes
-----------------

As a standard library module, `unittest` should not define any classic
classes.

Redundant names
---------------

The current API, with two or in some cases three different names
referencing exactly the same function, leads to an overbroad and
redundant API that violates PEP 20 ("there should be one, and
preferably only one, obvious way to do it").

PEP 8 names
-----------

Although `unittest` (and its predecessor `PyUnit`) are intended to be
familiar to users of other xUnit interfaces, there is no attempt at
direct API compatibility since the only code that Python's `unittest`
interfaces with is other Python code. The module is in the standard
library and its names should all conform with PEP 8.


Backwards Compatibility
=======================

The names to be obsoleted should be deprecated and removed according
to the schedule for modules in PEP 4.

While deprecated, use of the deprecated attributes should raise a
``DeprecationWarning``, with a message stating which replacement name
should be used.


Reference Implementation
========================

None yet.


Copyright
=========

This document is hereby placed in the public domain by its author.


..
    Local Variables:
    mode: rst
    coding: utf-8
    End:
    vim: filetype=rst :



More information about the Python-Dev mailing list