1. 程式人生 > >轉載 ddt原始碼修改:HtmlTestRunner報告依據介面名顯示用例名字

轉載 ddt原始碼修改:HtmlTestRunner報告依據介面名顯示用例名字

背景是這樣的:

  自己寫了一套介面自動化的框架,其中使用unittest + ddt + excel作為資料驅動模式的應用,使用HtmlTetstRunner來生成測試用例。

        一切看起來很完美。

        但是,發現測試報告中,測試用例名稱都是:test_api_index.index表示用例的編號,從1開始,遞增。比如:test_api_01、test_api_02......test_api_0N

        希望能在不同的用例名稱當中,顯示相應的介面用例名字。比如登陸介面的成功登陸用例:測試報告中用例名稱顯示為test_login_success。密碼錯誤的用例名稱為:test_login_wrongPasswd

        這樣,我直接從報告中就可以知道是哪個介面的哪個用例失敗了,一目瞭然。

       於是,就開始琢磨這事兒了。。。

 

======================================背景分割線============================================

 

        一琢磨就琢磨到ddt原始碼上去了。心中有一個疑惑:

       1、為什麼我的測試用例名稱是這樣的??

        查看了ddt原始碼之後,發現有個函式是用來生成測試用例名字的。這個函式叫:mk_test_name

  它是如何來生成測試用例名字的呢?

        它接受兩個引數:name 和 value.

         name:為單元測試中,測試用例的名字。即test_api.

         value:為測試資料。ddt是處理一組測試資料。而這個value就是這一組資料中的每一個測試資料。

                     對value的值是有限制的:要麼就是單值變數,要麼就是元組或者列表並且要求元組和列表中的資料都是單值變數。如("name","port") 、["name","port"]

         如果傳進來的測試資料,不符合value的要求,那麼測試用例名字為:name_index。

         如果傳進來的測試資料,符合value的要求,那麼測試用例名字為:name_index_value。如果value為列表或者元組,那麼將列表/元組的每個資料依次追加在末尾。

         比如傳進來的name值為test_login,value值為["name","port"]。那最終的測試用例名字是:test_login_01_name_port。

         如果傳進來的name值為test_login,value值為{"name":"login","port":2204},那最終的測試用例名字為:test_login_01。因為它不支援對字典型別的資料處理。

         很不巧,我的介面自動化框架中,ddt處理的資料是一列表:列表當中每個資料都為字典。ddt一遍歷整個列表,那傳給value的值剛好是字典。。

        so。。。我得到的測試用例名稱就是:test_api_01,test_api_02,test_api_03..........test_api_0N

def mk_test_name(name, value, index=0):
    """
    Generate a new name for a test case.
 
    It will take the original test name and append an ordinal index and a
    string representation of the value, and convert the result into a valid
    python identifier by replacing extraneous characters with ``_``.
 
    We avoid doing str(value) if dealing with non-trivial values.
    The problem is possible different names with different runs, e.g.
    different order of dictionary keys (see PYTHONHASHSEED) or dealing
    with mock objects.
    Trivial scalar values are passed as is.
 
    A "trivial" value is a plain scalar, or a tuple or list consisting
    only of trivial values.
    """
    
    # Add zeros before index to keep order
    index = "{0:0{1}}".format(index + 1, index_len)
    if not is_trivial(value):    #如果不符合value的要求,則直接返回用例名稱_下標作為最終測試用例名字。
        return "{0}_{1}".format(name, index)
    try:
        value = str(value)
    except UnicodeEncodeError:
        # fallback for python2
        value = value.encode('ascii', 'backslashreplace')
    test_name = "{0}_{1}_{2}".format(name, index, value)
    return re.sub(r'\W|^(?=\d)', '_', test_name)

2、修改ddt原始碼,顯示測試用例名字

       為了讓我的測試報告,呈現的更好。那就改改ddt原始碼,讓它能夠適應我的框架。

       考慮兩個問題:

        1、不同介面的測試用例名字如何來??

        2、如何讓ddt支援對字典的處理??

        解決方法:

        第一個問題:每一個測試用例主動提供一個用例名字,說明你是什麼介面的什麼場景用例。比如:介面名_場景名。login_success、login_noPasswd、login_wrongPasswd等。

        在我的框架當中,每一個測試用例是一個字典。那麼我就在字典中新增一個鍵值對,case_name=用例名稱

  第二個問題:在ddt中新增對字典的處理,如果字典中有case_name欄位,則將字典中鍵名為case_name的值作為測試用例名稱中的value值。

       修改後的ddt原始碼為(紅色粗體部分為修改的內容):

def mk_test_name(name, value, index=0):

    print("-------first value------------")
    print(value)
    # Add zeros before index to keep order
    index = "{0:0{1}}".format(index + 1, index_len)
    #添加了對字典資料的處理。
    if not is_trivial(value) and type(value) is not dict:
        return "{0}_{1}".format(name, index)
    #如果資料是字典,則獲取字典當中的api_name對應的值,加到測試用例名稱中。
    if type(value) is dict:
        try:
            value = value["case_name"]   #case_name作為value值
        except:
            return "{0}_{1}".format(name, index)
    try:
        value = str(value)
    except UnicodeEncodeError:
        # fallback for python2
        value = value.encode('ascii', 'backslashreplace')
    test_name = "{0}_{1}_{2}".format(name, index, value)

    return re.sub(r'\W|^(?=\d)', '_', test_name)

 

修改完成之後,再次執行介面測試,就可以在測試報告當中看到對應的用例名字啦。。

 轉載自:https://www.cnblogs.com/Simple-Small