qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          MBT框架(MTest)的實現(xiàn)用到的技術(shù)探討

           MBT框架的實現(xiàn)需要用到2種技術(shù):參數(shù)組合技術(shù)與代碼生成技術(shù)。

            參數(shù)組合技術(shù):抽象出測試場景的參數(shù),并對參數(shù)做等價類及邊界值分析后,利用迪卡爾乘積對多類參數(shù)進行組合,并過濾掉不需要組合,這里多半是用例建模時需要考慮。框架需要提供的是組合算法與過濾算法,用戶在使用這些算法的比較易懂、實用。

            代碼生成技術(shù):框架應能執(zhí)行模型代碼,執(zhí)行模型后能生成可執(zhí)行的測試代碼,這有點類似病毒,代碼執(zhí)行后,能產(chǎn)生出與自己等價的代碼。舉例如下:

            原始模型代碼:

          from MTest import TestCaseBase, Model, Scenario, Action, Assert, Logger

          @Action(DespFormat="Called with {0}, {1}")
          def JustReturnArg1(arg1, arg2):
          if arg1 == 1:
          return arg2
          return arg1

          @Model()
          class SimpleModel(TestCaseBase):

          @Scenario(Param={
          'p1':[1, 2],
          'p2':['a', 'b']
          }, Where={'combine':['p1','p2'],'strategy':'add'})

          def TestJustReturnSelf(self):
          Logger.Step('Call JustReturnSelf and Validate')
          p1 = self.Param['p1']
          p2 = self.Param['p2']
          rsp = JustReturnArg1(p1, p2)
          Assert.AreEqual(p1, rsp, 'p1 check')
          if __name__ == '__main__':
          import sys
          from MTestLauncher import MTestLoader
          MTestLoader.Run(None, False, "MTestRunConfig.xml", [sys.argv[0]],
          "mtest")

            在執(zhí)行后,生成3個測試用例

          @Model(TestModule="")
          def SimpleModel(TestCaseBase):

          @Scenario(Param={'p1': 1, 'p2': 'a'})
          def TestJustReturnSelf_p1(self):

          Logger.Step("Call JustReturnSelf and Validate")
          rsp1 = JustReturnArg1(self.Param["p1"],
          self.Param["p2"])
          Assert.AreEqual(self.Param["p1"], rsp1, "p1 check")

          @Scenario(Param={'p1': 1, 'p2': 'b'})
          def TestJustReturnSelf1_p2(self):

          Logger.Step("Call JustReturnSelf and Validate")
          rsp1 = JustReturnArg1(self.Param["p1"],
          self.Param["p2"])
          Assert.AreEqual(self.Param["p1"], rsp1, "p1 check")

          @Scenario(Param={'p1': 2, 'p2': 'a'})
          def TestJustReturnSelf2_p1(self):

          Logger.Step("Call JustReturnSelf and Validate")
          rsp1 = JustReturnArg1(self.Param["p1"],
          self.Param["p2"])
          Assert.AreEqual(self.Param["p1"], rsp1, "p1 check")

            以SpecExplore為例:

            <!--[if !supportLists]-->1.  <!--[endif]-->開發(fā)出建模腳本,通過解析腳本結(jié)合接口定義生成出測試用例。但這樣的偽代碼的開發(fā)成本和使用難道都比較大,沒有語法檢查,幾乎靠經(jīng)驗摸索著使用。

            <!--[if !supportLists]-->2.  <!--[endif]-->利用對象的屬性值變化作為模型轉(zhuǎn)換的狀態(tài)。對于初學者,來定位一個模型邏輯問題,難度和要求都是很高的。

            <!--[if !supportLists]-->3.  <!--[endif]-->在執(zhí)行模型時,根據(jù)在腳本中對模型接口定義好的枚舉參數(shù)進行組合并且根據(jù)模型實現(xiàn)確定每一個參數(shù)。

            在MTest中,建模與一般的寫測試用例的方式是一致,先進行參數(shù)組合,再執(zhí)行模型,模型通過一個全局屬性獲取參數(shù)或者直接傳給測試用例。為使能生成代碼,在執(zhí)行模型過程需要記住模型的執(zhí)行路徑,攔截住執(zhí)行每個接口函數(shù)調(diào)用的入?yún)⒑推诖妮敵觥F渲校诖妮敵鍪菑膶涌诘男r炛蝎@取。因此,攔截接口函數(shù)調(diào)用的入?yún)⑴c輸出是關(guān)鍵的技術(shù)。

            從語言層面看,要攔截函數(shù)的入?yún)⒑洼敵觯?/p>

            <!--[if !supportLists]-->1.  <!--[endif]-->Java里有spring可以做些攔截,但創(chuàng)建對象的必須從spring的容器中獲取。即使通過這種攔截能達到上面的效果,將其引入測試,配置和使用會異常復雜。

            <!--[if !supportLists]-->2.  <!--[endif]-->C#跟Java類似,C++就更不可能了。

            只能求助腳本語言了,Python語言的一個特性剛好可以做到這一點:獲取Python對象的屬性或函數(shù)都是通過__getattribute__來做到的,在定義類時覆蓋這個函數(shù),返回包裝好這個函數(shù)執(zhí)行的代理函數(shù),就可以攔截函數(shù)的入?yún)ⅰ?zhí)行和給出一個模擬的輸出。以一個例子說明如下:

          class A:
          def __getattribute__(self, name):
          print("Here, can return a delegate for function: %s, not just itself" % name)
          return object.__getattribute__(self, name)
          def bFun(self):
          print('b Called')
          A().bFun()

            輸出:

            Here, can return a delegate for function: bFun, not just itself

            b Called

            實際上,在mtest模式執(zhí)行模型時,MTest中對bFun的代理函數(shù)并不會真實的去執(zhí)行bFun,而是直接返會了一個動態(tài)結(jié)果DynamicResult,交給Assert.AreEqual去校驗,而Assert.AreEqual也不會被真正的執(zhí)行,而是僅僅是記住這個動態(tài)結(jié)果的期望值。這就知道了函數(shù)執(zhí)行時的入?yún)⒑洼敵觥R虼耍灰且玫絼討B(tài)結(jié)果的函數(shù)都應該是能被代理掉的。否則,這個函數(shù)得到將是一個未知的動態(tài)結(jié)果對象。從另外一個角度看,這實際上是對函數(shù)調(diào)用的一次Mock!

            另注:MTest里標記為@Action的函數(shù)和所有以Logger和Assert開始的函數(shù)都是能被代理掉的;能生成Python的代碼,引入不同的代碼生成技術(shù),同樣可以生成Java,C#,Ruby,JS、JMeter性能測試腳本的代碼

          posted on 2013-07-30 09:58 順其自然EVO 閱讀(368) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          <2013年7月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          導航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 顺昌县| 裕民县| 丹凤县| 增城市| 长沙市| 凭祥市| 广元市| 巍山| 桐城市| 桓仁| 晋州市| 龙游县| 五河县| 安远县| 沙坪坝区| 乃东县| 金沙县| 崇明县| 南江县| 郴州市| 宁乡县| 安义县| 兴化市| 泊头市| 盐源县| 宜兰市| 兴山县| 文水县| 金沙县| 勃利县| 昭觉县| 漳州市| 内江市| 大宁县| 呈贡县| 龙泉市| 奎屯市| 天台县| 漯河市| 六盘水市| 承德市|