unittest如何在循環遍歷一條用例時生成多個測試結果


引用自:http://blog.csdn.net/kaku21/article/details/42124593

 

參考網址:http://programmaticallyspeaking.com/test-data-provider-using-python-metaclass.html

使用TestNG進行測試的時候,允許使用外部數據源來驅動測試方法的執行,舉個例子:

我們有一個測試方法,而這個測試方法對應有10條測試數據,如果我們在測試方法中使用循環遍歷這十條數據的話,很可能出現的問題是:

1.測試中的斷言 assert 遇到一條數據執行結果錯誤時,退出測試方法

2.剩余的數據無法繼續執行,產生的數據報告不完整

解決上述問題的方法,利用TestNG的dataprodvider在測試類中獲取外部數據,然后傳給測試方法,這樣做到每一條數據驅動一次測試方法的執行,測試方法按數據量自動產生方法序號,報告測試結果。當某一條數據執行結果錯誤的時候,該方法對應的產生一次失敗信息,但不影響下一條數據的執行。

在測試報告中,看到的是某一個方法,然后產生了多少條報告。

關於TestNG數據驅動的詳情可以參考 http://testng.org/doc/documentation-main.html#parameters-dataproviders

 

我們要說的是,在python的unittest中沒有類似的方法,當我們需要遍歷測試數據的時候怎樣更好的去查看結果生成報告呢?

目前我沒有找到比較好的第三方組件,唯一的方式是自己來改寫,參看下面的代碼

<pre><span class="kn">import</span> <span class="nn">unittest</span>  
  
<span class="k">class</span> <span class="nc">DataProviderSupport</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>  
    <span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="n">classname</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">classDict</span><span class="p">):</span>  
        <span class="c"># method for creating our test methods</span>  
        <span class="k">def</span> <span class="nf">create_test_method</span><span class="p">(</span><span class="n">testFunc</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>  
            <span class="k">return</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">:</span> <span class="n">testFunc</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>  
  
        <span class="c"># look for data provider functions</span>  
        <span class="k">for</span> <span class="n">attrName</span><span class="p">,</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">classDict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>  
            <span class="k">if</span> <span class="n">attrName</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"dataprovider_"</span><span class="p">):</span>  
                <span class="c"># find out the corresponding test method</span>  
                <span class="n">testName</span> <span class="o">=</span> <span class="n">attrName</span><span class="p">[</span><span class="mi">13</span><span class="p">:]</span>  
                <span class="n">testFunc</span> <span class="o">=</span> <span class="n">classDict</span><span class="p">[</span><span class="n">testName</span><span class="p">]</span>  
<span class="c"># the test method is no longer needed</span>  
                <span class="k">del</span> <span class="n">classDict</span><span class="p">[</span><span class="n">testName</span><span class="p">]</span>  
  
                <span class="c"># generate test method variants based on</span>  
                <span class="c"># data from the data porovider function</span>  
                <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span>  
                <span class="k">for</span> <span class="n">args</span> <span class="ow">in</span> <span class="n">attr</span><span class="p">():</span>  
                    <span class="n">classDict</span><span class="p">[</span><span class="n">testName</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)]</span> <span class="o">=</span> <span class="n">create_test_method</span><span class="p">(</span><span class="n">testFunc</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>  
                    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>  
  
        <span class="c"># create the type</span>  
        <span class="k">return</span> <span class="nb">type</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">meta</span><span class="p">,</span> <span class="n">classname</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">classDict</span><span class="p">)</span>  

  

這里其實用到了元類的概念,也就是,我們重寫的type元類的__new__函數

驗證一下:

class TestStringLength(unittest.TestCase):  
    __metaclass__ = DataProviderSupport  
  
    def dataprovider_test_len_function(): # no self!  
        yield ("abc", 3)  
        yield ("", 0)  
        yield ("a", 1)  
  
    def test_len_function(self, astring, expectedLength):  
        self.assertEqual(expectedLength, len(astring))  

  運行 python的unittest,結果如下:

 

元類的概念,請參考:

http://www.ibm.com/developerworks/cn/linux/l-pymeta/

http://blog.csdn.net/b2b160/article/details/4161189

這個函數能夠返回當前類的類名稱,類字典,同時可以創建測試方法 即 create_test_method

當有多個測試數據對應一個測試方法時,我們把測試方法增加了序號,如果在后續引用測試方法時,需要在測試方法名稱后面添加序號

例如 suite.addTest(Testdriver(methodname+sn))

 

 

 

 

 http://www.cnblogs.com/fnng/p/8185172.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM