一个菜鸟测试工程师的简易自动化测试框架

上一篇 / 下一篇  2012-09-07 11:24:05 / 个人分类:自动化测试

~ ?z:tA a{-W8yI@0  引子

[Ke2G(]T*m051Testing软件测试网,ol*f9T&pQ1I$bz D7fd

  作为一个无 dev 经验的 tester 来说,目前遇到许多新的问题,关于 tester 以后的人员基本素质的构成,现在也有许多说法,在这里,不想过多的铺开讨论了。 作为一个 tester,本身当然必须对test这件事情感兴趣,才能把工作做好。 有的人天生喜欢找茬,喜欢提意见,在我看来,就是一个不错的 tester 的料。 当你天天对着同一个产品的不同版本不停的测试的时候,自然会产生一些怨言,由此产生懈怠。

%{ T[ uX+Z&`{D0

'SH9F cW&Eve0   “某些功能点我都连着测试了 N 个版本了,肯定不会出错了” “这种基本功能点,怎么可能出错”这样的论调是很有可能产生的。于是,一个 tester 很有可能在某次 release 的过程中,经验主义的放过了某些功能点的测试。 几天后,一个用户反馈上来,那个功能点出了问题.........

Q-K(G0r_0

nYZ(lb0  “偷懒”这个词语,在测试过程中,不应该算一个贬义词(当然了,故意漏过功能点不测试,不在此列)。因为“偷懒”催生新的技术,“偷懒”节省更多的时间。 我相信,自动化测试就是这样来的。

8h4g,h1t!kmxX,YAd;j051Testing软件测试网Uk:_fA5_]1J

  正题

+I%H"]cUPTQ!T t#W0

;W+?:Qx|5J|3m0  任何事情都可以分解为很小的部分,让我们先分析一下,手工执行测试案例的一个过程:

/f|5i gP1S0

r_h T0Lc2M)wm0  打开被测软件

#GW;OK#h9L'E2I0

l8Ll"m\Z i0  执行测试案例

hV#a,Y-duz0

'T ]n^:C8C0  给出测试结果

3Cf nqYg2VJ1m051Testing软件测试网 x^S6m"li Rc({

  然后,我们不断重复这个过程。 最后给出测试报告。

-q#E!`8F"H}0

5x;~+jHUI2\#z1CG `0  显然,我们的自动化测试也要满足上面的这个过程中的所有要求。 既然是自动化,首先要求是所有的测试用例可以无人值守运行;其次,每个测试用例都由机器来模拟人对软件的操作;第三,某个测试用例失败不能影响其他测试用例的继续执行;第四,测试数据和测试用例最好分离开来;最后一点,测试结束之后,给个报告或者给个图告知测试结果。

3[6OE$vPmm0qv)q0

BX+Y jn q0  根据上面的分析,我们逐个来一一解决,当然了,本篇都是很初级的解决方式,相信有许多大牛会有更好的方式来解决。

/A#Q)ks9x(]0

y T+hd T!rIb0  无人值守运行,那么 python 的 unittest 的框架就能达到这个目的。51Testing软件测试网J:ks5|v6LrJ

9jw\2?]-EO"TO0y0  模拟人的操作, selenium 可以胜任。51Testing软件测试网a"J}T-u+b

51Testing软件测试网8pq^{5U]1Ds

  测试用例间无影响, 同1

&{h tY,q051Testing软件测试网f9Z B8G O#I

  数据分离, 那把测试数据都扔xml里。51Testing软件测试网 K:qE+gYW7@

0i:uq@*IAe0  待完善 (本例中 只是在部分方法中添加错误提示)51Testing软件测试网BF-j[9er7v:F

,N:B-B;N3y6oBw-n0  开始动手

cy t ] a)pS051Testing软件测试网&G(Q s HvU

  对 python 的 unittest 进行一些小手术,当然了,如果只追求简单,直接用也行。51Testing软件测试网tS?W x)Fa

def assertLogEqual(self, arg1, arg2):51Testing软件测试网ERw#_Y!Q
print "[assertLogEqual('"+arg1+"', '"+arg2+"')]: "51Testing软件测试网)xc.L:?"A$EZ;J [6D#D-B
if arg1 != arg2:
4Ir5L{*DZFO0self.anyfailure = True
-iVy2~h9S0print " -> Failed: not equal"
:A@ S6Hu0u2TV0l0self.result_note = " '%s' and 's%' is not equal\n "%(arg1,arg2)51Testing软件测试网I!s#TUl4f
else:51Testing软件测试网Z B?&H]z,CFY
print " ->OK"
n hM{%k0self.result_note = "%s OK\n" % self.result_note51Testing软件测试网lRv7Nt
self.assertEqual(arg1, arg2)51Testing软件测试网ETbT"LH!nJ0r
def assertLogTrue(self, arg1, note=""):
:pe ]{{;d0print "[assertLogTrue("+str(arg1)+")]: "+note51Testing软件测试网I2S(T7M Kr-J
if arg1 is False:51Testing软件测试网8bU]'Q"V'yy
self.anyfailure = True51Testing软件测试网 tl R(hW{ Jj5r4m
print " -> Failed: Excepting True"
z&cly{*s0self.result_note = " %sError: %s\n " % (self.result_note, note)51Testing软件测试网"UK9o(?.Be$o^C5C*E
else:51Testing软件测试网e4q4IZ'Y!dg0`
print " ->OK"51Testing软件测试网K|!~ zphR,LO
self.resulte_note = "%s OK\n" % self.result_note
O_#_%M'^1E!a eQ:jb0self.assertTrue(arg1)
#uJ_ q9eM ^)Q)U6T0def assertLogFalse(self, arg1, note=""):
^)W)Zi ]7x k)N/h0print "[assertLogFalse("+str(arg1)+")]: "+note51Testing软件测试网&w+}4?U^2x(Dj
if arg1 is True:
}cT k QjrL0print " ->FAILED: Expecting False."
yk.Cv l G9r`0self.anyfailure = True
|P!K9Qu;V\!EF L8z$Z0self.result_note = "%sError: %s\n" % (self.result_note, note)
/ex:g;P2W0else:
@a or8[*LoG F,v0self.result_note = "%sOK\n" % self.result_note51Testing软件测试网X%? Bt+X&Zo
print " ->OK"
1J~_+? n)n@0self.assertFalse(arg1)
pA8Q r"Q/U0BY],v0
51Testing软件测试网M y L?;D'J

  自己新建一个类,继承unittest,然后修改必要的一些方法,并添加部分方法,譬如设置testName啊,设置标记值来标记case知否执行结束啊。这些都是可以根据自己喜好来加入的方法。

3XMP,Q-NP,{,c O0

6S[J0Y?Z1R%S051Testing软件测试网c'J2a |9r

def setTestName(self, tname):
#^f:h5fQe0self.testname = tname
f&tm2K%CgW0def getTestName(self):
*P*WQ*m7Q5m'Ip0return self.testname51Testing软件测试网4r"dP.h L kp
def setCompleted(self):
9K b1u'b2E{Z4v0self.completed = True51Testing软件测试网1~^H5@vN*A
def isCompleted(self):
q/tGQe X0return self.completed
51Testing软件测试网*O!_Yw0{F(M2M@

  对于unittest框架的修改 就写这么多。

*| n)I7E"?@-f3sl#C0

[8M5BD/y3P9lhc0  对selenium的基本方法做一些小改动,动机优化 unittest 框架一致,只是为了让你的用例跑起来的时候更加让人理解。我们相当于在 selenium 的基本方法外面又封装了一层。下面是部分方法示例:51Testing软件测试网s3[PcSz^0QN+@

51Testing软件测试网$\puNS`s!V1DK

%D X]X,I0
def open(self,url):
`uX6Qv#B5e0self.sel.open(url)51Testing软件测试网+fk/Qk%P;a H&m:M
def GetValue(self, element):
"C_J$M@?q!K7B7V0value = self.sel.get_value(element)
gO_+?6t$pq4@0self.assertLogTrue(True, "Value for element %s is %s" %(element, value))
Cgp.z"}9|/?7zS)H5w0return value
"@.tm$h%G0def isTextPresent(self, text):51Testing软件测试网Qx8v$r&[&T'|se
val = self.sel.is_text_present(text)
M:~G!P,Q3uRD7s0if val is False:51Testing软件测试网^u4e b3v |
self.assertLogTrue(val, note="error occured *************" + text +\
(uq0e^)d8p0" not found")51Testing软件测试网O H"rv4n j
else:
1fW&QL ` `0print 'present (%s,%s)' % (text,val)51Testing软件测试网/Epkc#@2q&H
return val51Testing软件测试网.i {Vb4ZGn?
def Select(self, element, selection):
e5C(N*FaG0if self.isElementPresent(element):51Testing软件测试网&RjI#`,NG f
self.sel.select(element, selection)51Testing软件测试网6IIQ u@'tS o
def Check(self, element):
^3},VQ.]h'f0if self.isElementPresent(element):
q)@`C}]W0o n0self.sel.check(element)
b8aaz/rN1P"va0def Type(self, element, text):51Testing软件测试网l$`&mf:P2e
if self.isElementPresent(element):
&AV"C i$i0self.sel.type(element, text)

4s:~ Qz%y0  测试数据分离,这个做的非常简单,就是把期望值和控件位置作为测试数据放入 xml 中。

[RVn o051Testing软件测试网9j7irHci x;S

/DVO#vS @4Sq0
GWEB
nxzO(~)i+G2Jf(vc0link
4ORA8G$bm)A0//span[text()="Web"]
}5@?7r#T8[.g/f:zA0Web
'i Cc9~D-[~:f/`0GIMAGES51Testing软件测试网4FM^5{7rB ]A
link51Testing软件测试网QeJx }[.Ob_
//span[text()="Images"]
Q*w1AArv5b0Images

&L:flH$L0E0  name 表示控件名字,type 为控件的类型,locator 表示控制位置,expect_value 表示期望值。

B/l;O4Q@4xg051Testing软件测试网;SIA7m$S#t%v']9X1K

  读取 xml 的内容。这段代码属于我现学现卖,直接看了一下 python 对 xml 的支持,然后自己捣鼓了一下就写出来了,可以获取自己需要的 xml 里面的数据。

.D[![BHeHs[/j0

ouFkJ0

?{)J'm"C3X~nV0
from xml.dom import minidom
4d3r9iA/CSU0class PageData():51Testing软件测试网o2b8hyGD8C|b-K
def __init__(self, page_name, file):
W0K*q7Gg5M.}0self.name = page_name
P&tBO#x,Y({0self.data = minidom.parse(file)
Ue"ZG {0self.xpth_dict = self.XML_Dict()51Testing软件测试网)L%z!`ItVQ{
def XML_Dict(self):
4L^R#lYJbrX0xpath_dict = {}
"ld nZ P-H_G}h0for i in self.data.getElementsByTagName(self.name):
4JK0{ s8Y3G{0xpath_dict[str(i.childNodes[1].firstChild.nodeValue)] = \51Testing软件测试网$GgZ,o2\FD&g
[str(i.childNodes[5].firstChild.nodeValue),\51Testing软件测试网$\`fX8~ o3q
str(i.childNodes[7].firstChild.nodeValue)]51Testing软件测试网0g-zzh_;K.~
return xpath_dict
?E1C W0B"r,[u|0def GetLocator(self, object_name):51Testing软件测试网 v9_5tXc-OB
return self.xpth_dict[object_name][0]
%c]'oXb8Ss*V0def GetValue(self, object_name):
Dzj'Yn~W*f0return self.xpth_dict[object_name][1]
51Testing软件测试网(I}1Ox~#o+H

  最后,主程序里面,我们就能用下面的方式,执行我们本来已经设计好的案例。51Testing软件测试网3HJ R6OCET

51Testing软件测试网|5R"^5s%^h

}~b:hO,p0
def testAutoCompleteFunctionMouseMove(self):
VD}\G]8_1Y|0'''test the function of auto complete. case 2: when user move mouse to the suggestion, there will be a link '''51Testing软件测试网5bWrZ2y4H
self.initTest("testAutoCompleteFunctionMouseMove")
-}z*EMGGQ F0self.open('http://www.google.com/ncr')
@6_S U e uz6~!c0GoogleHomePage = data_parser.PageData("GoogleHomePage", self.data_file)
cSr:~g&H0self.Type(GoogleHomePage.GetLocator('SEARCHTEXT'), 's')51Testing软件测试网 Gz NVc N/g y^
GoogleAutoComplete = data_parser.PageData("AutoCompleteCase", self.data_file)51Testing软件测试网JdDF:~4mD
self.isElementPresent(GoogleAutoComplete.GetLocator("SUGGESTIONFIELD"))51Testing软件测试网i(X&}:C9v0nX.J
time.sleep(10)51Testing软件测试网5y/r3LK2sH*ZW&~A
self.MouseMove(GoogleAutoComplete.GetLocator("SUGGESTIONONEFORS"))
f,b$feW6rBw$d0expect_text = "I'm Feeling Lucky ?"
|+?-iU/irq0self.assertLogTrue(self.isTextPresent(expect_text), "The text %s has been displayed" %expect_text)
Tq0]E%Z w0self.MouseMove(GoogleAutoComplete.GetLocator("SUGGESTIONTWOFORS"))
!z5u6^0g3UL.o9P0time.sleep(10)
'OA/O.f {'[7f b0self.assertLogTrue(self.isTextPresent(expect_text), "The text %s has been displayed" %expect_text)
2ih8k'GyZ,b0self.endTest()

'H}Ci^at5k0  这样,一个相当简易的自动化测试框架基本完工。可以完善的地方实在太多了,希望有志之士去完善吧,加入些新功能,譬如错误出现的时候截图,然后统计测试用例总数以及通过的数量。51Testing软件测试网?/^%X6r^ n+T

D9p'ec.Hj5R+X0  后记51Testing软件测试网0wN a#KTp ~ B

j)xKn7mb mw2}0  作为一个菜鸟测试工程师,没有任何的开发经验,搞出这个东西还是有点小激动的,也激发了本人对许多事情的兴趣。 以后希望能有更好的 test frame. 去学习去创造。51Testing软件测试网)Qa%F?6GvLV+X


-[~UG(l2@0e"V0

TAG:

虫师 引用 删除 fnngj   /   2014-02-14 18:50:46
写得太笼统,修改的文件的代码也讲清楚。
 

评分:0

我来说两句

Open Toolbar