A. python題求解答!
如果你聽說過「測試驅動開發」(TDD:Test-Driven Development),單元測試就不陌生。
單元測試是用來對一個模塊、一個函數或者一個類來進行正確性檢驗的測試工作。
比如對函數abs(),我們可以編寫出以下幾個測試用例:
輸入正數,比如1、1.2、0.99,期待返回值與輸入相同;
輸入負數,比如-1、-1.2、-0.99,期待返回值與輸入相反;
輸入0,期待返回0;
輸入非數值類型,比如None、[]、{},期待拋出TypeError。
把上面的測試用例放到一個測試模塊里,就是一個完整的單元測試。
如果單元測試通過,說明我們測試的這個函數能夠正常工作。如果單元測試不通過,要麼函數有bug,要麼測試條件輸入不正確,總之,需要修復使單元測試能夠通過。
單元測試通過後有什麼意義呢?如果我們對abs()函數代碼做了修改,只需要再跑一遍單元測試,如果通過,說明我們的修改不會對abs()函數原有的行為造成影響,如果測試不通過,說明我們的修改與原有行為不一致,要麼修改代碼,要麼修改測試。
這種以測試為驅動的開發模式最大的好處就是確保一個程序模塊的行為符合我們設計的測試用例。在將來修改的時候,可以極大程度地保證該模塊行為仍然是正確的。
我們來編寫一個Dict類,這個類的行為和dict一致,但是可以通過屬性來訪問,用起來就像下面這樣:
>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d.a
1
mydict.py代碼如下:
class Dict(dict):
def __init__(self, **kw):
super(Dict, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
為了編寫單元測試,我們需要引入Python自帶的unittest模塊,編寫mydict_test.py如下:
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEquals(d.a, 1)
self.assertEquals(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEquals(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEquals(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
編寫單元測試時,我們需要編寫一個測試類,從unittest.TestCase繼承。
以test開頭的方法就是測試方法,不以test開頭的方法不被認為是測試方法,測試的時候不會被執行。
對每一類測試都需要編寫一個test_xxx()方法。由於unittest.TestCase提供了很多內置的條件判斷,我們只需要調用這些方法就可以斷言輸出是否是我們所期望的。最常用的斷言就是assertEquals():
self.assertEquals(abs(-1), 1) # 斷言函數返回的結果與1相等
另一種重要的斷言就是期待拋出指定類型的Error,比如通過d['empty']訪問不存在的key時,斷言會拋出KeyError:
with self.assertRaises(KeyError):
value = d['empty']
而通過d.empty訪問不存在的key時,我們期待拋出AttributeError:
with self.assertRaises(AttributeError):
value = d.empty
運行單元測試
一旦編寫好單元測試,我們就可以運行單元測試。最簡單的運行方式是在mydict_test.py的最後加上兩行代碼:
if __name__ == '__main__':
unittest.main()
這樣就可以把mydict_test.py當做正常的python腳本運行:
$ python mydict_test.py
另一種更常見的方法是在命令行通過參數-m unittest直接運行單元測試:
$ python -m unittest mydict_test
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
這是推薦的做法,因為這樣可以一次批量運行很多單元測試,並且,有很多工具可以自動來運行這些單元測試。
setUp與tearDown
可以在單元測試中編寫兩個特殊的setUp()和tearDown()方法。這兩個方法會分別在每調用一個測試方法的前後分別被執行。
setUp()和tearDown()方法有什麼用呢?設想你的測試需要啟動一個資料庫,這時,就可以在setUp()方法中連接資料庫,在tearDown()方法中關閉資料庫,這樣,不必在每個測試方法中重復相同的代碼:
class TestDict(unittest.TestCase):
def setUp(self):
print 'setUp...'
def tearDown(self):
print 'tearDown...'
可以再次運行測試看看每個測試方法調用前後是否會列印出setUp...和tearDown...。
小結
單元測試可以有效地測試某個程序模塊的行為,是未來重構代碼的信心保證。
單元測試的測試用例要覆蓋常用的輸入組合、邊界條件和異常。
單元測試代碼要非常簡單,如果測試代碼太復雜,那麼測試代碼本身就可能有bug。
單元測試通過了並不意味著程序就沒有bug了,但是不通過程序肯定有bug。
B. python斷言assertequals是什麼意思
根據老外的解釋就是說assertEqual與assertEquals沒有區別,可以說是完全一樣的函數,而現在assertEquals函數已經被棄用,也就說不建議你使用了,以後可能這個方法就在python中消失了,在python3.0中已經趨向使用不帶s的assert方法了,但是現在仍然沒有刪掉的原因是因為有一些舊代碼和項目在使用帶s的方法,語言要保持舊代碼的兼容性。
至於assert那就很好解釋了,就是判斷0,1 也就是python中的真假關系
assertAlmostEquals這2個方法存在的原因與上面的相同,建議你不要使用帶s的方法了,這個方法是做一個粗略判斷,判斷的值為你4舍5入後的值,也就是說5.1與5.2是相等的,如果使用這樣的assert方法。
C. 有沒有技術大牛了解java開發,測試和CI的關
大家可能對如下情景比較熟悉:
如果開發過SSH的web項目,啟動伺服器可能會比較慢,有的項目甚至需要1分多鍾,甚至更多,這個啟動時間的等待一般就浪費了;
在開發項目時,有些功能比較復雜,當時覺得思路特清晰,但是過了一段時間後,自己也忘了,完善功能時頻繁出現bug,降低開發速度;
在維護項目時,不知道自己修改的對還是不對,是否存在隱患;維護速度降下來了;
如果開發一個很多人都使用的介面,典型的如用戶系統,要保證比如升級時向下兼容;
在團隊間協作時,有時候只定義好介面,對方還沒有給實現,如何進行同步開發?
如上問題,估計只要是個開發人員,都可能遇到過;如果此時有了單元/集成測試,那我們能很好的解決這些問題。(註:加下來如果沒有特殊情況,不刻意強調 單元測試/集成測試,即提到測試是指的是單元/集成測試)
我從以下幾個方面介紹測試:
1、為什麼需要測試?
2、如何進行測試?
3、測試有哪些好處?
4、一切都需要測試嗎?
1、為什麼需要測試?
測試的目的是什麼?我的理解是:
縮短發現問題到解決問題的速度;
給程序一個修改後能驗證是否正確的保證;(回歸測試)
如果是開源軟體,我們可以通過單元測試了解其是怎麼使用的;比如我之前通過cglib的單元測試學習過cglib的使用;
所以如果你遇到如上問題,就需要寫測試。寫測試可能是為了自己(1、2);也可能是為了幫助別人(3)。
2、如何進行測試?
很多朋友不知道如何進行測試,其實測試很簡單,別把它想復雜了,按照自己的想法測試每個功能點是否正確即可。
2.1、測試流程
單元測試流程
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>native2ascii-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>native2ascii</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<src>src/main/messages</src>
<dest>target/${project.artifactId}/WEB-INF/classes</dest>
<includes>messages.properties</includes>
</configuration>
</execution>
</executions>
<!--native2ascii使用的tools.jar-->
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.7.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</plugin>
如果使用mysql,埠只能是3306。
如果想開埠測試,這是不允許的。
如下是我項目中的一個配置.travis.yml,放到項目的根下即可:
-----------------------------------
language: java 語言
env: 環境
- DB=mysql 使用mysql
jdk:
- openjdk jdk使用openjdk
mysql:
database: es 資料庫名為es
username: root 用戶名為root
password : 密碼為空
encoding: utf8 編碼為utf8
install: 安裝時執行的腳本
- mvn install -Dmaven.test.skip=true mvn安裝並跳過測試
before_script: script之前執行的測試
- cd web
- mvn db:create 創建資料庫的mvn命令(此處使用了maven-db-plugin 插件)
- mvn db:schema 創建腳本的mvn命令
- mvn db:data 安裝數據的mvn命令
- cd ..
script: 測試時執行的腳步
- cd common
- mvn test 測試common子模塊
- cd ..
- cd web
- mvn test -Pit 測試web子模塊,並指定使用it profile測試(即集成測試的配置,具體參考pom.xml中的profile/it)
notifications: 觸發
email: 測試完成後測試報告發到哪
-----------------------------------
持續集成不能修復代碼的錯誤,而是和單元測試一樣,縮短發現問題帶解決問題的時間,這樣可以提高開發效率,降低項目風險,提高項目的穩定性。而且尤其是團隊協作時,可以發現其他人的代碼是否對自己的代碼產生影響。
到此我們利用單元測試+CI可以加速開發人員的開發速度。利用好單元測試和CI,不要純粹為了單元測試和CI而去做這些事情。
本文沒有介紹TDD,TDD並不會那麼美好,我認為我們可以借鑒TDD的一些思想,但決不能迷信TDD,有時候,尤其如開發企業應用,先寫功能再寫測試可能效率更高,而且大部分時候是不需要TDD的。而且我也沒能在實際項目中獲取太多TDD的好處,但是我獲得了測試的好處。
本文也沒有介紹測試覆蓋率,我認為不要一味的追求覆蓋率,有時候有的覆蓋率沒有任何意義。所以不要讓為了覆蓋率而覆蓋率拖慢了項目開發進度。
正如stackoverflow上的一篇帖子《How deep are your unit tests?》上Kent Beck的回答:
寫道
老闆為我的代碼付報酬,而不是測試,所以,我對此的價值觀是——測試越少越好,少到你對你的代碼質量達到了某種自信。
可以前往coolshell的「單元測試要做多細?」去得到一些經驗。
D. junit4啟動測試時發生java.lang.NullPointerException的錯誤
排查問題
1,查看各位引用,Appium,selenium,junit的包都包含了,在Build
path裡面設置正確,此處沒有問題。
2,APK的各種情況,版本安裝是否正確,要測試的和提供的APK的版本是否一致。經查看,是一致的,此處Pass!
3,Capabilities各種參數的設置,對比了網上提供的實例和我以前用Python寫的,運行成功的測試用例的設置,發現完全一致,也沒有任何問題。
4,現在只好查看一下Eclipse的問題了,查看WorkSpace下的.metadata文件夾下的.log文件,看一下是否存在問題。
經查看,發現有org.eclipse.jdt.junit相關的錯誤,於是我就在Eclipse下查找這個jdt.junit相關的插件,發現沒有找到,現在問題就定位到了,肯定是這個插件出問題了!!
解決問題
問題描述:Eclipse下缺少org.eclipse.jdt.junit相關的插件,造成用junit運行測試用例的時候,報空指針的錯誤!!!
網上查看了一下JDT相關的東西,發現中能是我這個Eclipse下載的是ADT版本的,當時用來做Appium
python版和Robotium的測試的。這個版本的Eclipse沒有SDK。於是去網上下載了一個eclipse-jee-luna-SR1-win32-x86_64,解壓後,再按Appium
java環境搭建的方法配置了一下,寫了個Demo再次運行,成功!!
順便,android提供的的eclipes無法使用junit4,也需要重新下載。望採納。
E. 用python單元測試怎麼測一段代碼
單元測試是用來對一個模塊、一個函數或者一個類來進行正確性檢驗的測試工作。
比如對函數abs(),我們可以編寫出以下幾個測試用例:
輸入正數,比如1、1.2、0.99,期待返回值與輸入相同;
輸入負數,比如-1、-1.2、-0.99,期待返回值與輸入相反;
輸入0,期待返回0;
輸入非數值類型,比如None、[]、{},期待拋出TypeError。
把上面的測試用例放到一個測試模塊里,就是一個完整的單元測試。
如果單元測試通過,說明我們測試的這個函數能夠正常工作。如果單元測試不通過,要麼函數有bug,要麼測試條件輸入不正確,總之,需要修復使單元測試能夠通過。
單元測試通過後有什麼意義呢?如果我們對abs()函數代碼做了修改,只需要再跑一遍單元測試,如果通過,說明我們的修改不會對abs()函數原有的行為造成影響,如果測試不通過,說明我們的修改與原有行為不一致,要麼修改代碼,要麼修改測試。
這種以測試為驅動的開發模式最大的好處就是確保一個程序模塊的行為符合我們設計的測試用例。在將來修改的時候,可以極大程度地保證該模塊行為仍然是正確的。
我們來編寫一個Dict類,這個類的行為和dict一致,但是可以通過屬性來訪問,用起來就像下面這樣:
>>> d = Dict(a=1, b=2)
>>> d['a']
1
>>> d.a
1
mydict.py代碼如下:
class Dict(dict):
def __init__(self, **kw):
super(Dict, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
為了編寫單元測試,我們需要引入Python自帶的unittest模塊,編寫mydict_test.py如下:
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEquals(d.a, 1)
self.assertEquals(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEquals(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEquals(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
編寫單元測試時,我們需要編寫一個測試類,從unittest.TestCase繼承。
以test開頭的方法就是測試方法,不以test開頭的方法不被認為是測試方法,測試的時候不會被執行。
對每一類測試都需要編寫一個test_xxx()方法。由於unittest.TestCase提供了很多內置的條件判斷,我們只需要調用這些方法就可以斷言輸出是否是我們所期望的。最常用的斷言就是assertEquals():
self.assertEquals(abs(-1), 1) # 斷言函數返回的結果與1相等
另一種重要的斷言就是期待拋出指定類型的Error,比如通過d['empty']訪問不存在的key時,斷言會拋出KeyError:
with self.assertRaises(KeyError):
value = d['empty']
而通過d.empty訪問不存在的key時,我們期待拋出AttributeError:
with self.assertRaises(AttributeError):
value = d.empty
運行單元測試
一旦編寫好單元測試,我們就可以運行單元測試。最簡單的運行方式是在mydict_test.py的最後加上兩行代碼:
if __name__ == '__main__':
unittest.main()
這樣就可以把mydict_test.py當做正常的python腳本運行:
$ python mydict_test.py
另一種更常見的方法是在命令行通過參數-m unittest直接運行單元測試:
$ python -m unittest mydict_test
.....
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
這是推薦的做法,因為這樣可以一次批量運行很多單元測試,並且,有很多工具可以自動來運行這些單元測試。
setUp與tearDown
可以在單元測試中編寫兩個特殊的setUp()和tearDown()方法。這兩個方法會分別在每調用一個測試方法的前後分別被執行。
setUp()和tearDown()方法有什麼用呢?設想你的測試需要啟動一個資料庫,這時,就可以在setUp()方法中連接資料庫,在tearDown()方法中關閉資料庫,這樣,不必在每個測試方法中重復相同的代碼:
class TestDict(unittest.TestCase):
def setUp(self):
print 'setUp...'
def tearDown(self):
print 'tearDown...'
可以再次運行測試看看每個測試方法調用前後是否會列印出setUp...和tearDown...。
F. junit4啟動測試時發生java.lang.NullPointerException的錯誤
排查問題
1,查看各位引用,Appium,selenium,junit的包都包含了,在Build path裡面設置正確,此處沒有問題。
2,APK的各種情況,版本安裝是否正確,要測試的和提供的APK的版本是否一致。經查看,是一致的,此處Pass!
3,Capabilities各種參數的設置,對比了網上提供的實例和我以前用Python寫的,運行成功的測試用例的設置,發現完全一致,也沒有任何問題。
4,現在只好查看一下Eclipse的問題了,查看WorkSpace下的.metadata文件夾下的.log文件,看一下是否存在問題。
經查看,發現有org.eclipse.jdt.junit相關的錯誤,於是我就在Eclipse下查找這個jdt.junit相關的插件,發現沒有找到,現在問題就定位到了,肯定是這個插件出問題了!!
解決問題
問題描述:Eclipse下缺少org.eclipse.jdt.junit相關的插件,造成用junit運行測試用例的時候,報空指針的錯誤!!!
網上查看了一下JDT相關的東西,發現中能是我這個Eclipse下載的是ADT版本的,當時用來做Appium python版和Robotium的測試的。這個版本的Eclipse沒有SDK。於是去網上下載了一個eclipse-jee-luna-SR1-win32-x86_64,解壓後,再按Appium java環境搭建的方法配置了一下,寫了個Demo再次運行,成功!!
順便,android提供的的eclipes無法使用junit4,也需要重新下載。望採納。