qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          代碼測試(CodeTest)

          1.  什么是代碼測試?與傳統的功能和接口測試有什么不同?
            代碼測試的立足點是Code,是基于代碼基礎之上的,而傳統的功能測試和接口測試是基于應用的,必須對應的測試系統是在運行中的。
            代碼測試不會特別注重接口測試的可持續性集成。
            代碼測試的特點是快捷高效準確的完成測試工作,快速推進產品的迭代。
            2.  Code Test 的方法:
            (1)  代碼走讀和review
            適合場景:邏輯相對簡單,有較多的邊界值。
            方法介紹:直接查看和閱讀代碼,檢驗邏輯是否正確。
            (2)  代碼debug與代碼運行中測試
            適合場景:數據構造比較困難,特殊的場景覆蓋。
            方法介紹:1.直接在debug代碼過程中查看數據流走向,校驗邏輯。
            2.在debug過程中直接將變量的值或者對象的值直接改成想要的場景
            (3)  私有方法測試
            適合場景:需要測試的類的復雜邏輯處理是放在一個特定的方法中,而且該方法中沒有使用到其他引用的bean
            方法介紹:通過反射的方式調用方法,進行測試。
            例子:
            假設有一個待測試的類叫MyApp,有一個私有方法叫getSortList, 參數是一個整形List。
          /**
          * Created by yunmu.wgl on 2014/7/16.
          */
          public class MyApp {
          private List  getSortList(List<Integer> srcList){
          Collections.sort(srcList);
          return srcList;
          }
          }
            那么測試類的代碼如下:
          /**
          * Created by yunmu.wgl on 2014/7/16.
          */
          public class MyAppTest {
          @Test
          public  void testMyApp() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
          Class clazz = MyApp.class;
          Method sortList = clazz.getDeclaredMethod("getSortList",List.class); //獲取待測試的方法
          sortList.setAccessible(true); //私有方法這個是關鍵
          List<Integer> testList = new ArrayList<Integer>();//構造測試數據
          testList.add(1);
          testList.add(3);
          testList.add(2);
          MyApp myApp = new MyApp(); // 新建一個待測試類的對象
          sortList.invoke(myApp,testList); //執行測試方法
          System.out.println(testList.toString()); //校驗測試結果
          }
          }
           (4)  快速搭建測試腳本環境
            適合場景:待測試的方法以hsf提供接口方法,或者需要測試的類引入了其他bean 配置。
            方法介紹:直接在開發工程中添加測試依賴,主要是junit,如果是需要測試hsf接口,則加入hsf的依賴,如果需要使用itest的功能,加入itest依賴。
            Junit 的依賴一般開發都會加,主要看下junit的版本,最好是4.5 以上
            HSF的測試依賴:以前的hsfunit 和hsf.unit 最好都不要使用了。
            <dependency>
            <groupId>com.taobao.hsf</groupId>
            <artifactId>hsf-standalone</artifactId>
            <version>2.0.4-SNAPSHOT</version>
            </dependency>
            Hsf 接口測試代碼示例:
            // 啟動HSF容器,第一個參數設置taobao-hsf.sar路徑,第二個參數設置HSF版本
            HSFEasyStarter.start("d:/tmp/", "1.4.9.6");
            String springResourcePath = "spring-hsf-uic-consumer.xml";
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(springResourcePath);
            UicReadService uicReadService = (UicReadService) ctx.getBean("uicReadService");
            // 等待相關服務的地址推送(等同于sleep幾秒,如果不加,會報找不到地址的錯誤)
            ServiceUtil.waitServiceReady(uicReadService);
            BaseUserDO user = uicReadService.getBaseUserByUserId(10000L, "detail").getModule();
            System.out.println("user[id:10000L] nick:" + user.getNick());
            Hsf bean的配置示例:
            <beans>
            <bean name="uicReadService" class="com.taobao.hsf.app.spring.util.HSFSpringConsumerBean"
            init-method="init">
            <property name="interfaceName" value="com.taobao.uic.common.service.userinfo.UicReadService" />
            <property name="version" value="1.0.0.daily" />
            </bean>
            </beans>
            Itest的依賴:這個版本之前修復了較多的bug。
            <dependency>
            <groupId>com.taobao.test</groupId>
            <artifactId>itest</artifactId>
            <version>1.3.2.1-SNAPSHOT</version>
            <dependency>
            (5)  程序流程圖校驗
            適合場景:業務流程的邏輯較為復雜,分支和異常情況很多
            方法介紹:根據代碼邏輯畫出業務流程圖,跟實際的業務邏輯進行對比驗證,是否符合預期。
            (6)  結對編程
            適合場景:代碼改動較小,測試和開發配對比較穩定
            方法介紹:開發修改完代碼后,將修改部分的邏輯重復給測試同學,測試同學review 開發同學講述的邏輯是否和代碼的邏輯一致。
            3.   具體操作步驟:
            (1)  checkout代碼,在接手項目和日常后第一件事情是checkout 對應的應用的代碼
            (2)  了解數據結構與數據存儲關系:了解應用的數據對象和數據庫的表結構及存儲關系。
            (3)  了解代碼結構, 主要搞清楚代碼的調用關系。
            (4)  了解業務邏輯和代碼的關系:業務邏輯肯定是在代碼中實現的,找到被測試的業務邏輯對應的代碼,比較常見的是通過url 或者接口名稱等。
            如果是webx框架的可以根據http請求找到對應的代碼,如果是其他框架的也可以通過http請求的域名在配置文件中找到對應的代碼。
            (5)  閱讀相關代碼,了解數據流轉過程。
            (6)  Review 代碼,驗證條件,路徑覆蓋。
            (7)  復雜邏輯可以選用寫腳本測試或者私有方法測試,或者畫出流程圖。
            4.  代碼測試的常見測試場景舉例:
            (1)  條件,邊界值,Null 測試:
            復雜的多條件,多邊界值如果要手工測試,會測試用例非常多。而且null值的測試往往構造數據比較困難。
            例如如下的代碼:
          if (mm.getIsRate() == UeModel.IS_RATE_YES) {
          float r;
          if (value != null && value.indexOf(‘.’) != -1) {
          r = currentValue – compareValue;
          } else {
          r = compareValue == 0 ? 0 : (currentValue – compareValue) / compareValue;
          }
          if (r >= mm.getIncrLowerBound()) {
          score = mm.getIncrScore();
          } else if (r <= mm.getDecrUpperBound()) {
          score = mm.getDecrScore();
          }
          mr.setIncreaseRate(formatFloat(r));
          } else {
          // 目前停留時間為非比率對比
          if (currentValue – compareValue >=mm.getIncrLowerBound()) {
          score = mm.getIncrScore();
          } else if (currentValue – compareValue <= mm.getDecrUpperBound()) {
          score = mm.getDecrScore();
          }
          }
          (2)  方法測試
            某個方法相對比較獨立,但是是復雜的邏輯處理
            例如下面的代碼:
          private void filtSameItems(List<SHContentDO> contentList) {
          Set<Integer> sameIdSet = new TreeSet<Integer>();
          Set<Integer> hitIdSet = new HashSet<Integer>();
          for (int i = 0; i < contentList.size(); i++) {
          if (sameIdSet.contains(i) || hitIdSet.contains(i)) {
          continue;
          }
          SHContentDO content = contentList.get(i);
          List<Integer> equals = new ArrayList<Integer>();
          equals.add(i);
          if ("item".equals(content.getSchema())) {
          for (int j = i + 1; j < contentList.size(); j++) {
          SHContentDO other = contentList.get(j);
          if ("item".equals(other.getSchema()) && content.getReferItems().equals(other.getReferItems())) {
          equals.add(j);
          }
          }
          }
          if (equals.size() > 1) {
          Integer hit = equals.get(0);
          SHContentDO hitContent = contentList.get(hit);
          for (int k = 1; k < equals.size(); k++) {
          SHContentDO other = contentList.get(k);
          if (hitContent.getFinalScore() == other.getFinalScore()) {
          long hitTime = hitContent.getGmtCreate().getTime();
          long otherTime = other.getGmtCreate().getTime();
          if (hitTime > otherTime) {
          hit = equals.get(k);
          hitContent = other;
          }
          } else {
          if (hitContent.getFinalScore() < other.getFinalScore()) {
          hit = equals.get(k);
          hitContent = other;
          }
          }
          }
          for (Integer tmp : equals) {
          if (tmp != hit) {
          sameIdSet.add(tmp);
          }
          }
          hitIdSet.add(hit);
          }
          }
          Integer[] sameIdArray = new Integer[sameIdSet.size()];
          sameIdSet.toArray(sameIdArray);
          for (int i = sameIdArray.length - 1; i >= 0; i--) {
          contentList.remove((int) sameIdArray[i]);
          }
          }

          posted on 2014-10-30 10:46 順其自然EVO 閱讀(592) 評論(0)  編輯  收藏 所屬分類: 測試學習專欄

          <2014年10月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 阿图什市| 怀安县| 霍林郭勒市| 安庆市| 桦甸市| 永新县| 唐海县| 西宁市| 北票市| 遵义市| 兴化市| 廉江市| 辽源市| 尤溪县| 阳东县| 丹棱县| 育儿| 洪洞县| 梅州市| 金乡县| 西吉县| 黄龙县| 永清县| 饶河县| 汉川市| 金门县| 景泰县| 潮州市| 昔阳县| 江山市| 西城区| 衡阳县| 嘉定区| 瑞丽市| 安平县| 仙游县| 黄平县| 八宿县| 西乌| 长治县| 寿宁县|