Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Customizing Test Case Names in DDT for Readable HtmlTestRunner Reports

Tech May 16 3

When conducting API testing using unittest, DDT, and Excel, test reports generated with HtmlTestRunner often display generic test case names such as test_api_1, test_api_2, test_api_3. These names lack clarity and make it difficult to identify specific test scenarios at a glance.

Improving test case naming to something descriptive like test_api_login_success or test_api_password_error would significantly enhance report readability. This modification would allow team members, including non-technical stakeholders, to easily understand which tests passed or failed and take appropriate action without needing to reference Excel line numbers.

The key to implementing this enhancement lies in modifying the mk_test_name function within the DDT source code, which is responsible for generating test case names.

Original mk_test_name Implementation

def mk_test_name(base_name, test_data, case_index=0):
    """
    Generate a descriptive name for a test case.
    
    This function creates a unique test name by combining the original test name,
    an ordinal index, and a string representation of the test data.
    The result is converted into a valid Python identifier by replacing invalid characters.
    
    For complex data structures, we avoid direct string conversion to prevent
    inconsistent naming across different test runs (e.g., due to dictionary key ordering).
    Simple scalar values are used directly.
    
    A "simple" value is defined as a plain scalar, or a tuple/list containing
    only simple values.
    """
    
    # Pad index with leading zeros to maintain ordering
    case_index = "{0:0{1}}".format(case_index + 1, index_length)
    if not is_simple(test_data):
        return "{0}_{1}".format(base_name, case_index)
    try:
        test_data = str(test_data)
    except UnicodeEncodeError:
        # Fallback for Python 2
        test_data = test_data.encode('ascii', 'backslashreplace')
    test_name = "{0}_{1}_{2}".format(base_name, case_index, test_data)
    return re.sub(r'\W|^(?=\d)', '_', test_name)

Modified Implementation for Descriptive Naming

To extract meaningful test names from test data, we can modify the mk_test_name function to check if the input data is a dictionary or tuple and extract a 'name' or 'title' field when available.

def mk_test_name_with_labels(base_name, test_data, case_index=0):
    """
    Generate descriptive test names by extracting meaningful labels from test data.
    
    This enhanced version checks if the test data is a dictionary or tuple
    and attempts to extract a 'name' or 'title' field to create more readable
    test case names.
    
    Args:
        base_name: The original test method name
        test_data: The test data (can be various types)
        case_index: The index of the test case in the data set
        
    Returns:
        A descriptive test case name
    """
    
    # Pad index with leading zeros to maintain ordering
    case_index = "{0:0{1}}".format(case_index + 1, index_length)
    
    # Handle dictionary test data
    if isinstance(test_data, dict):
        if 'name' in test_data:
            return "{0}_{1}_{2}".format(base_name, case_index, test_data['name'])
        elif 'title' in test_data:
            return "{0}_{1}_{2}".format(base_name, case_index, test_data['title'])
        else:
            return "{0}_{1}".format(base_name, case_index)
    
    # Handle tuple test data
    if isinstance(test_data, tuple) and len(test_data) > 0:
        if isinstance(test_data[0], dict) and 'name' in test_data[0]:
            return "{0}_{1}_{2}".format(base_name, case_index, test_data[0]['name'])
        
    # Fallback to original implementation for other data types
    if not is_simple(test_data):
        return "{0}_{1}".format(base_name, case_index)
    
    try:
        test_data = str(test_data)
    except UnicodeEncodeError:
        # Fallback for Python 2
        test_data = test_data.encode('ascii', 'backslashreplace')
    
    test_name = "{0}_{1}_{2}".format(base_name, case_index, test_data)
    return re.sub(r'\W|^(?=\d)', '_', test_name)

Implementation Notes

To apply this modification, replace the original mk_test_name function in your DDT installation with the enhanced version above. Your test data should include a 'name' or 'title' field when you want descriptive test case names in the report.

For example, with test data structured as:

test_data = [
    {"name": "login_success", "username": "user1", "password": "pass1"},
    {"name": "password_error", "username": "user2", "password": "wrong"}
]

The resulting test case names in the HtmlTestRunner report will be:

  • test_api_1_login_success
  • test_api_2_password_error

This approach significantly improves the readability and usefulness of your test reports.

Tags: ddt

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.