<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

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

    項(xiàng)目開發(fā)中切換部署開發(fā)、測試、生產(chǎn)多環(huán)境

    在開發(fā)的過程中,不可避免會(huì)接觸到至少三個(gè)環(huán)境的程序部署:開發(fā)、測試和生產(chǎn)環(huán)境。
      每個(gè)環(huán)境都使用一套數(shù)據(jù)庫配置,路徑配置等,如果每次都人工的干預(yù)每一個(gè)配置文件,工作會(huì)比較繁雜,且容易遺漏并且出錯(cuò)。
      spring3.1之后提供了profile功能,可以切換不同的自定義profile環(huán)境,唯一的缺點(diǎn)是和maven結(jié)合不大好,只能在web.xml中進(jìn)行修改。
      方法如下:
      1、在beans.xml中定義各個(gè)環(huán)境。
    <beans profile="develop">
    </beans>
    <beans profile="test">
    </beans>
    <beans profile="product">
    </beans>
      每個(gè)環(huán)境如果使用了不同的配置文件(properties文件等)可以在環(huán)境中進(jìn)行加載聲明。
      該段代碼需在文件根節(jié)點(diǎn)的最后一段
      如
      <beans profile="test">
      <context:property-placeholder location="classpath*:jdbc-test.properties"/>
      </beans>
      2、定義屬性之外的配置,如指定數(shù)據(jù)庫bean等
    <beans profile="test,develop">
    <bean id="authDataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
    </property>
    <property name="url"
    value="jdbc:oracle:thin:@208.120.102.10:1522:ora11g">
    </property>
    <property name="username" value="user"></property>
    <property name="password" value="passwd"></property>
    </bean>
    </beans>
    <beans profile="product">
    <bean id="authDataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver">
    </property>
    <property name="url"
    value="jdbc:oracle:thin:@198.121.33.7:1521:ora10g">
    </property>
    <property name="username" value="user"></property>
    <property name="password" value="passwd"></property>
    </bean>
    </beans>
    此處定義了不同環(huán)境下不同的數(shù)據(jù)庫鏈接信息
      3、web.xml中定義當(dāng)前使用哪個(gè)環(huán)境
      在web.xml中操作context-param節(jié)點(diǎn)
      <context-param>
      <param-name>spring.profiles.active</param-name>
      <param-value>product</param-value>
      </context-param>
      部署時(shí)指定哪個(gè)環(huán)境為激活狀態(tài)即可。
      如果進(jìn)行junit測試可以使用
      @ActiveProfiles({"test","develop"})
      附: 如果spring的profile可以和maven的發(fā)布共同作用就更好了,但是筆者目前還未能成功將2者結(jié)合。
      配置提醒:
      <beans xmlns="http://www.springframework.org/schema/beans" profile="test,develop" -----設(shè)置這個(gè)之后,數(shù)據(jù)庫只對test,develop有效
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
      <!-- 定義數(shù)據(jù)連接池 -->
      <!-- 使用spring自帶的DriverManagerDataSource方式 -->

    posted @ 2014-06-13 09:56 順其自然EVO 閱讀(569) | 評(píng)論 (1)編輯 收藏

    Sql Server中REPLACE函數(shù)的使用

      在sql的使用過程當(dāng)中,我們偶爾會(huì)遇到這樣一種情況,就是需要改變數(shù)據(jù)的存儲(chǔ)形式,比如數(shù)據(jù)庫某一張表(Info)當(dāng)中有一個(gè)字段Educational(學(xué)歷),以前存儲(chǔ)的是Json數(shù)組,現(xiàn)在由于需求的改變,我需要將數(shù)據(jù)的存儲(chǔ)形式改成Json格式,這樣我們就需要對數(shù)據(jù)進(jìn)行替換,當(dāng)數(shù)據(jù)量太大時(shí),人工操作明顯是不可取的,所以作者就找到了sql當(dāng)中的REPLACE函數(shù),下面分享一下我的個(gè)人體會(huì)。
      REPLACE
      用第三個(gè)表達(dá)式替換第一個(gè)字符串表達(dá)式中出現(xiàn)的所有第二個(gè)給定字符串表達(dá)式。
      語法
      REPLACE ( ''string_replace1'' , ''string_replace2'' , ''string_replace3'' )
      參數(shù)
      ''string_replace1''
      待搜索的字符串表達(dá)式。string_replace1 可以是字符數(shù)據(jù)或二進(jìn)制數(shù)據(jù)。
      ''string_replace2''
      待查找的字符串表達(dá)式。string_replace2 可以是字符數(shù)據(jù)或二進(jìn)制數(shù)據(jù)。
      ''string_replace3''
      替換用的字符串表達(dá)式。string_replace3 可以是字符數(shù)據(jù)或二進(jìn)制數(shù)據(jù)。
      返回類型
      如果 string_replace(1、2 或 3)是支持的字符數(shù)據(jù)類型之一,則返回字符數(shù)據(jù)。
      如果 string_replace(1、2 或 3)是支持的 binary 數(shù)據(jù)類型之一,則返回二進(jìn)制數(shù)據(jù)。
      示例
      下例用 xxx 替換 abcdefghi 中的字符串 cde。
      SELECT REPLACE(''abcdefghicde'',''cde'',''xxx'')GO
      下面是結(jié)果集:
      ------------abxxxfghixxx(1 row(s) affected)
      那么如何直接對數(shù)據(jù)進(jìn)行修改呢?
      首頁,我們要實(shí)現(xiàn)的是對表中存儲(chǔ)的數(shù)據(jù)進(jìn)行修改,那么一定會(huì)有 Update,其次,我們需要把我們的數(shù)據(jù)進(jìn)行替換,那么一定會(huì)有 REPLACE。
      得出的sql語句如下:
      update [Info] set [Educational] =(select REPLACE(REPLACE([Educational],'[',''),']',''))
      執(zhí)行以上的Sql語句,就會(huì)把表中存儲(chǔ)的數(shù)據(jù)全部從Json數(shù)組變?yōu)镴son字符串了。

    posted @ 2014-06-12 13:07 順其自然EVO 閱讀(216) | 評(píng)論 (0)編輯 收藏

    Java transient關(guān)鍵字使用小記

       3. transient使用細(xì)節(jié)——被transient關(guān)鍵字修飾的變量真的不能被序列化嗎?
      思考下面的例子:
    import java.io.Externalizable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    /**
    * @descripiton Externalizable接口的使用
    *
    * @author Alexia
    * @date 2013-10-15
    *
    */
    public class ExternalizableTest implements Externalizable {
    private transient String content = "是的,我將會(huì)被序列化,不管我是否被transient關(guān)鍵字修飾";
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(content);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
    ClassNotFoundException {
    content = (String) in.readObject();
    }
    public static void main(String[] args) throws Exception {
    ExternalizableTest et = new ExternalizableTest();
    ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
    new File("test")));
    out.writeObject(et);
    ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
    "test")));
    et = (ExternalizableTest) in.readObject();
    System.out.println(et.content);
    out.close();
    in.close();
    }
    }
      content變量會(huì)被序列化嗎?好吧,我把答案都輸出來了,是的,運(yùn)行結(jié)果就是:
      是的,我將會(huì)被序列化,不管我是否被transient關(guān)鍵字修飾
      這是為什么呢,不是說類的變量被transient關(guān)鍵字修飾以后將不能序列化了嗎?
      我們知道在Java中,對象的序列化可以通過實(shí)現(xiàn)兩種接口來實(shí)現(xiàn),若實(shí)現(xiàn)的是Serializable接口,則所有的序列化將會(huì)自動(dòng)進(jìn)行,若實(shí)現(xiàn)的是Externalizable接口,則沒有任何東西可以自動(dòng)序列化,需要在writeExternal方法中進(jìn)行手工指定所要序列化的變量,這與是否被transient修飾無關(guān)。因此第二個(gè)例子輸出的是變量content初始化的內(nèi)容,而不是null。
     3. transient使用細(xì)節(jié)——被transient關(guān)鍵字修飾的變量真的不能被序列化嗎?
      思考下面的例子:
    import java.io.Externalizable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    /**
    * @descripiton Externalizable接口的使用
    *
    * @author Alexia
    * @date 2013-10-15
    *
    */
    public class ExternalizableTest implements Externalizable {
    private transient String content = "是的,我將會(huì)被序列化,不管我是否被transient關(guān)鍵字修飾";
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(content);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
    ClassNotFoundException {
    content = (String) in.readObject();
    }
    public static void main(String[] args) throws Exception {
    ExternalizableTest et = new ExternalizableTest();
    ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
    new File("test")));
    out.writeObject(et);
    ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
    "test")));
    et = (ExternalizableTest) in.readObject();
    System.out.println(et.content);
    out.close();
    in.close();
    }
    }
      content變量會(huì)被序列化嗎?好吧,我把答案都輸出來了,是的,運(yùn)行結(jié)果就是:
      是的,我將會(huì)被序列化,不管我是否被transient關(guān)鍵字修飾
      這是為什么呢,不是說類的變量被transient關(guān)鍵字修飾以后將不能序列化了嗎?
      我們知道在Java中,對象的序列化可以通過實(shí)現(xiàn)兩種接口來實(shí)現(xiàn),若實(shí)現(xiàn)的是Serializable接口,則所有的序列化將會(huì)自動(dòng)進(jìn)行,若實(shí)現(xiàn)的是Externalizable接口,則沒有任何東西可以自動(dòng)序列化,需要在writeExternal方法中進(jìn)行手工指定所要序列化的變量,這與是否被transient修飾無關(guān)。因此第二個(gè)例子輸出的是變量content初始化的內(nèi)容,而不是null。

    posted @ 2014-06-12 13:06 順其自然EVO 閱讀(206) | 評(píng)論 (0)編輯 收藏

    分布式測試執(zhí)行

      1 相關(guān)說明
      1.1 背景簡介
      隨著一個(gè)產(chǎn)品的自動(dòng)化工作不斷深入,自動(dòng)化的case積累數(shù)量持續(xù)增長,絕大部分毫無依賴關(guān)系的case由于串行運(yùn)行,測試執(zhí)行時(shí)間達(dá)到小時(shí)界別,且不易于優(yōu)化。另外,ci運(yùn)行時(shí)所需機(jī)器資源的搶占互斥,運(yùn)行機(jī)器的不穩(wěn)定等問題也逐漸擴(kuò)大。
      Hadoop分布式測試執(zhí)行方案正是為了解決以上問題而產(chǎn)生,通過分布式執(zhí)行,可以達(dá)到并行運(yùn)行,提高執(zhí)行效率的目的;另外,hadoop提供調(diào)度,重試等機(jī)制功能,可以提供給用戶一個(gè)相對透明的計(jì)算資源池,減少用戶對機(jī)器運(yùn)行環(huán)境的依賴。
      1.2 分布式平臺(tái)的選擇
      本方案采用hadoop來作為分布式平臺(tái)。首先是Hadoop是一個(gè)開源項(xiàng)目,有非常好的技術(shù)支持,二就是hadoop有成熟的分布式調(diào)度算法,可以很好的利用每臺(tái)機(jī)器的cpu和內(nèi)存資源,達(dá)到計(jì)算資源最優(yōu)分配,三就是hadoop程序易于編寫,便于維護(hù)。
      1.3 名詞解釋
     ?。篴pache基金會(huì)的開源分布式框架。
      Mapreduce :hadoop的計(jì)算模型,由map任務(wù)和reduce任務(wù)組成。
      Jobtracker  :hadoop計(jì)算系統(tǒng)的總控。
      Tasktracker  :hadoop計(jì)算系統(tǒng)的子節(jié)點(diǎn)。
      Slot(槽位) :tasktracker的最小計(jì)算分配單元,一個(gè)槽位可以對應(yīng)一個(gè)map任務(wù),一個(gè)機(jī)器啟動(dòng)一個(gè)tasktracker,槽位的話按照機(jī)器的cpu核數(shù)來分配,一般是”核數(shù)-1”。
      <2 分布式測試執(zhí)行方案
      2.1 傳統(tǒng)的單機(jī)測試執(zhí)行流程
      一般的單機(jī)測試流程分為5步,如下圖所示:
      1、lib庫安裝。包括測試框架的lib庫安裝以及基于該測試框架的產(chǎn)品業(yè)務(wù)層lib。
      2、測試環(huán)境安裝。主要指被測對象的測試環(huán)境安裝,包括數(shù)據(jù)庫安裝,server端安裝等。
      3、case下載。從svn或者case庫獲取需要執(zhí)行的case。
      4、case運(yùn)行。
      5、發(fā)送報(bào)告。
      單機(jī)測試執(zhí)行的優(yōu)點(diǎn)在于邏輯簡單,易于實(shí)現(xiàn),缺點(diǎn)就是case要串行執(zhí)行,無法有效里有機(jī)器的cpu和內(nèi)存資源。舉個(gè)例子,現(xiàn)在有一個(gè)8核16G的測試機(jī),每個(gè)case的平均cpu使用率為10%,內(nèi)存消耗1G,在這樣的情況,一般可以做到至少6個(gè)case并行化,優(yōu)化效率是不言而喻的。
      2.2 從單機(jī)測試到分布式測試執(zhí)行的邏輯
      有了以上的五個(gè)步驟及相關(guān)分析,我們考慮其中可以并行執(zhí)行來進(jìn)行優(yōu)化的就是測試執(zhí)行這塊了,其他lib庫安裝,測試環(huán)境安裝等都基本是最小單元,不易切分了。
      所以從單機(jī)到分布式主要是Case執(zhí)行集合的一個(gè)拆分。所以簡單說,單機(jī)和分布式的區(qū)別就是case輸入集合有變“而已,其他單機(jī)的測試執(zhí)行過程基本不變。對于測試工程師來說,這個(gè)過程是透明的,只是執(zhí)行case的環(huán)境從單機(jī)切換到多機(jī)。
      下圖簡要的表示了case從單機(jī)到多機(jī)的變化(6位的數(shù)字是caseid)。
      2.3 分布式運(yùn)行邏輯
      這里的邏輯主要是兩塊,一部分是本地部分,一部分是分布式節(jié)點(diǎn)機(jī)器部分。我們將分布式測試執(zhí)行過程封裝到一個(gè)hadoop job里。
      本地部分:
      1、獲取計(jì)算資源。這里的計(jì)算資源指可用的tasktracker的槽位數(shù),這個(gè)槽位是case切分的分母。
      2、根據(jù)計(jì)算資源生成case列表。有了槽位數(shù),最簡單的切分算法就是:每節(jié)點(diǎn)case數(shù)=總case數(shù)/槽位數(shù)。
      3、業(yè)務(wù)層自定義操作。例如業(yè)務(wù)層測試執(zhí)行時(shí)需要的程序或者配置獲取,依賴的大數(shù)據(jù)推送到hdfs等。
      4、配置hadoop的job。包括input,output,執(zhí)行job所需的文件或者tar包等。這里的input就是case列表。
      5、執(zhí)行測試執(zhí)行job。這個(gè)實(shí)際是個(gè)hadoop job。
      6、發(fā)送報(bào)告。匯總每個(gè)節(jié)點(diǎn)的運(yùn)行結(jié)果,并發(fā)出報(bào)告。
      每個(gè)tasktracker的map任務(wù)輸入是切分后的case列表,通過這種方式將整個(gè)測試執(zhí)行部分分發(fā)到每個(gè)tasktracker上。
      節(jié)點(diǎn)部分:
      1、準(zhǔn)備case列表。從map的input獲取。
      2、根據(jù)case列表下載case。,這里類似于本地單機(jī)版的case獲取,來源仍然是SVN或者CASE庫。
      3、安裝lib庫。同本地單機(jī)版。
      4、安裝測試環(huán)境。同本地單機(jī)版。
      5、執(zhí)行case。同本地單機(jī)版。
      6、推送報(bào)告。
      這里hadoop還會(huì)根據(jù)每個(gè)map任務(wù)的返回值,來進(jìn)行重試運(yùn)行的調(diào)度。
      從以上的描述可以看到,在hadoop集群節(jié)點(diǎn)機(jī)器上(tasktracker),測試執(zhí)行的邏輯和單機(jī)版基本無差別,所以整個(gè)改造的過程也是比較簡單的
      2.4 分布式測試集群架構(gòu)設(shè)計(jì)
      整個(gè)分布式測試執(zhí)行依托于一個(gè)公共的計(jì)算集群,這個(gè)計(jì)算集群由兩部分組成,一部分是hadoop相關(guān)的,包括hadoop的總控,子節(jié)點(diǎn)的tasktracker服務(wù)。另外一部分就是公共環(huán)境,包括測試框架,公共工具例如valgrind等。前者通過jobtracker來管理,后者通過統(tǒng)一運(yùn)維系統(tǒng)來管理,其功能基本就是公共環(huán)境的安裝和維護(hù)。
      3 收益
      經(jīng)過我們的實(shí)際項(xiàng)目實(shí)踐,這部分的收益主要體現(xiàn)在如下兩點(diǎn):
      1、測試執(zhí)行時(shí)間大幅優(yōu)化。15臺(tái)機(jī)器的情況,所有原測試執(zhí)行時(shí)間要1-2小時(shí)的模塊,優(yōu)化到10分鐘以內(nèi)。
      2、機(jī)器資源的節(jié)省。通過公共集群的維護(hù),保證所有機(jī)器cpu滿負(fù)荷運(yùn)作,避免了以往單機(jī)測試執(zhí)行的cpu浪費(fèi)。
      4 準(zhǔn)入原則及發(fā)展方向
      4.1 分布式改造的準(zhǔn)入原則
      并不是所有的測試執(zhí)行都可以分布式化,在我們的實(shí)際操作過程中,總結(jié)出以下幾點(diǎn)準(zhǔn)入原則,供參考:
      1、空白機(jī)器可運(yùn)行。通過一個(gè)總控腳本就可以做到依賴環(huán)境準(zhǔn)備,lib庫安裝,測試case執(zhí)行等。
      2、測試框架允許case并行。
      3、業(yè)務(wù)層case對外部不存在固定依賴,例如依賴于某個(gè)寫死的目錄。
      4、業(yè)務(wù)層case依賴的server端口,最好是隨機(jī)的。
      5、不允許業(yè)務(wù)層去操作公共環(huán)境。
      4.2 后續(xù)可能的技術(shù)方向
      1、case按照執(zhí)行時(shí)間切分。按照時(shí)間切分來替代按照case數(shù)切分。
      2、從分布式測試執(zhí)行過渡到云測試服務(wù)。

    posted @ 2014-06-12 13:05 順其自然EVO 閱讀(172) | 評(píng)論 (0)編輯 收藏

    Maven中配置生成單元測試報(bào)告配置

     對junit單元測試的報(bào)告:
      1.  -------------------------------------------------------
      2.   T E S T S
      3.  -------------------------------------------------------
      4.  Running com.liuyan.account.mail.AccountImageServiceImplTest
      5.  ---------------------------------1990
      6.  Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.926 sec
      7.  Running com.liuyan.account.mail.AccountImageUtilTest
      8.  Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
      9.
      10.  Results :
      12.  Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
      運(yùn)行報(bào)告是junit自己的報(bào)告輸出,和咱們在Eclipse運(yùn)行的報(bào)告差不多。以上代表運(yùn)行了3個(gè)用例,和預(yù)期效果不符的是0個(gè),失敗的用例是0個(gè),忽略的用例數(shù)是0個(gè)。
      如果需要跳過單元測試,則可以運(yùn)行如下命令
      1.  mvn package -DskipTests
      大家可能要問,為何Maven能夠自己尋找我們編寫的測試類呢?其實(shí)還是那句約定大于配置。Maven自動(dòng)去尋找src/test/java下面的類,當(dāng)此文件夾下面的類符合以下規(guī)范,那么Maven默認(rèn)認(rèn)為他們是單元測試用例類。
      Test*.java:任何目錄下以Test為開始的類
      *Test.java: 任何目錄下以Test為結(jié)尾的類
      *TestCase.java: 任何目錄下以TestCase為結(jié)尾的類。
      如果想在一段時(shí)間內(nèi)節(jié)省項(xiàng)目構(gòu)建時(shí)間,暫時(shí)全部忽略單元測試。那么可以在pom.xml中配置如下
    1.  <build>
    2.      <plugins>
    3.          <plugin>
    4.              <groupId>org.apache.maven.plugins</groupId>
    5.              <artifactId>maven-surefire-plugin</artifactId>
    6.              <version>2.5</version>
    7.              <configuration>
    8.                  <skipTests>true</skipTests>
    9.              </configuration>
    10.          </plugin>
    11.      </plugins>
    12.  </build>
      等到項(xiàng)目完全開發(fā)完了,需要測試用例的時(shí)候?qū)⑵渥⑨尩艏纯伞?br />
     本個(gè)模塊有兩個(gè)測試用例類,如果僅僅想運(yùn)行一個(gè)測試用例該怎么辦。運(yùn)行下面命令
      1.  test -Dtest=AccountImageServiceImplTest
      這個(gè)是指定具體運(yùn)行哪個(gè)測試用例。當(dāng)然需要將pom文件中忽略測試用例的配置注釋掉。
      也可以測試多個(gè)測試用例
      1.  mvn test -Dtest=AccountImageServiceImplTest,AccountImageUtilTest
      也可以使用模糊匹配進(jìn)行測試
      1.  mvn test -Dtest=*Test
    1.  <build>
    2.      <plugins>
    3.          <plugin>
    4.              <groupId>org.apache.maven.plugins</groupId>
    5.              <artifactId>maven-surefire-plugin</artifactId>
    6.              <version>2.5</version>
    7.              <configuration>
    8.                  <includes>
    9.                      <include>**/*Test.java</include>
    10.                  </includes>
    11.                  <excludes>
    12.                      <exclude>**/AccountImageUtilTest.java</exclude>
    13.                  </excludes>
    14.              </configuration>
    15.          </plugin>
    16.      </plugins>
    17.  </build>
      includes是需要測試的類,excludes是要排除之外測試用例。可以使用模糊匹配。**用來匹配任意件路經(jīng),*匹配任意類。
      Junit的單元測試報(bào)告:
    <reporting>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-report-plugin</artifactId>
    <version>2.12.2</version>
    <configuration>
    <showSuccess>false</showSuccess>
    </configuration>
    </plugin>
    </plugins>
    </reporting>
      這個(gè)默認(rèn)生成的報(bào)告是txt,要生成html的報(bào)告需要使用命令mvn surefire-report:report. 這會(huì)在target/site下面生成html的報(bào)告
      后來經(jīng)測試發(fā)現(xiàn),其實(shí)maven-surefire-plugin就已經(jīng)可以生成txt和xml的測試結(jié)果,如果要html的報(bào)告才需要maven-surefire-report-plugin
      4.  測試報(bào)告
      基本的測試報(bào)告上面已經(jīng)介紹過了,下面我們看看測試覆蓋率的報(bào)告。運(yùn)行如下命令
      1.  mvn cobertura:cobertura
      pom配置
    <project>
    ...
    <reporting>
    <plugins>
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.5.1</version>
    </plugin>
    </plugins>
    </reporting>
    ...
    </project>
      常用命令
      mvn cobertura:help          查看cobertura插件的幫助
      mvn cobertura:clean         清空cobertura插件運(yùn)行結(jié)果
      mvn cobertura:check         運(yùn)行cobertura的檢查任務(wù)
      mvn cobertura:cobertura     運(yùn)行cobertura的檢查任務(wù)并生成報(bào)表,報(bào)表生成在target/site/cobertura目錄下
      cobertura:dump-datafile     Cobertura Datafile Dump Mojo
      mvn cobertura:instrument    Instrument the compiled classes
      在target文件夾下出現(xiàn)了一個(gè)site目錄,下面是一個(gè)靜態(tài)站點(diǎn),里面就是單元測試的覆蓋率報(bào)告。
      詳細(xì)配置還可參考:http://zhanshenny.iteye.com/blog/1440571
      5.  總結(jié)
      這次我們介紹了Maven的測試,可以運(yùn)行項(xiàng)目的單元測試用例,并生成報(bào)告。使用者可以根據(jù)自己的需要配置測試選項(xiàng)以滿足項(xiàng)目的測試需求。最后說一下,測試十分重要,往往大手筆的產(chǎn)品測試人員和開發(fā)人員的比例是2:1。

    posted @ 2014-06-12 13:03 順其自然EVO 閱讀(7705) | 評(píng)論 (0)編輯 收藏

    UAT測試后上線出現(xiàn)問題的引起的思考

    最近公司有一個(gè)外部項(xiàng)目上線了,雖然我沒有參與這個(gè)項(xiàng)目,僅僅只是作為一個(gè)旁觀者,但是關(guān)于用戶的UAT測試的問題,不得表達(dá)下我的看法,
      在上線之前進(jìn)行了近一個(gè)月的UAT測試,測試完成后進(jìn)入了正式上線階段。但是在正式上線后還是出現(xiàn)了幾個(gè)讓人感覺不可思議的問題。
      首先是居然出現(xiàn)大面積的用戶電腦安裝系統(tǒng)不成功的問題,安裝成功后又出現(xiàn)了由于SSO的登錄不成功的問題。關(guān)于這2個(gè)問題,我覺得不應(yīng)該是
      在后期還會(huì)出現(xiàn)的問題,首先應(yīng)該在需求確認(rèn)和可行性分析階段就應(yīng)該驗(yàn)證的問題了。即使前期都沒有發(fā)現(xiàn),也應(yīng)該在UAT給暴露出來,但是居然在上線后才暴露出來。不得不令人深思這其中的原因。
      原因不外乎下面幾個(gè):
      1.項(xiàng)目團(tuán)隊(duì)前期并沒有將用戶的環(huán)境納入考慮范圍,或者沒有應(yīng)對過這種問題。
      2.設(shè)計(jì)系統(tǒng)時(shí)沒有進(jìn)行全面而認(rèn)真的分析,將問題想象的過于簡單了,結(jié)果導(dǎo)致上線后用SSO登錄其中的幾個(gè)系統(tǒng)都出現(xiàn)了問題。
      3.單元測試,集成測試,UAT測試時(shí)都沒有將這2個(gè)問題真正納入測試項(xiàng)。
      4.項(xiàng)目團(tuán)隊(duì)的每個(gè)人都很忙,都在疲于應(yīng)付各自任務(wù),根本沒有時(shí)間去思考這些看上去微不足到卻極為致命的問題。
      5.此外項(xiàng)目的溝通,需求確認(rèn)及需求調(diào)研也存在問題,沒有考慮周全可能出現(xiàn)意外,盲目樂觀,而且沒有任何緊急預(yù)案,也沒有給自己留下一個(gè)過渡的緩沖。
      綜合考慮以上問題,雖然這個(gè)項(xiàng)目自己沒有參與,但是覺得小結(jié)下還是有必要的,自己以后做項(xiàng)目也要引以為戒。

    posted @ 2014-06-12 13:03 順其自然EVO 閱讀(277) | 評(píng)論 (0)編輯 收藏

    Java發(fā)郵件:Java Mail與Apache Mail

    一、郵件簡介
      一封郵件由很多信息構(gòu)成,主要的信息如下,其他的暫時(shí)不考慮,例如抄送等:
      1、收件人:收件人的郵箱地址,例如xxx@xx.com
      2、收件人姓名:大部分的郵件顯示時(shí)都會(huì)顯示,例如loadfate 779554589@qq.com
      3、發(fā)件人:發(fā)件人的郵箱地址
      4、發(fā)件人姓名:
      5、主題:郵件的標(biāo)題
      6、內(nèi)容及附件:郵件的主要內(nèi)容
      二、使用Java發(fā)郵件的通用步驟
      一般的項(xiàng)目中沒有單獨(dú)的郵件服務(wù)器,一般情況下都是使用別人的服務(wù)器。
      1、設(shè)置smtp服務(wù)器:不同的郵件服務(wù)器有不同的地址,例如:smtp.qq.com表示騰訊的smtp服務(wù)器。
      2、授權(quán):使用該服務(wù)器的帳號(hào)和密碼登錄該服務(wù)器。
      3、創(chuàng)建郵件:創(chuàng)建一份包含所有信息的郵件,比如發(fā)件人、收件人、內(nèi)容等。
      4、設(shè)置郵件的屬性:為郵件的屬性添加數(shù)據(jù)。
      5、發(fā)送郵件:因?yàn)榉庋b不同,發(fā)送的方式不一致。
      三、Java Mail與Apache Mail
      Apache Mail是對Java Mail的封裝,使用起來更加的簡便,邏輯層次感更好。
      使用Java Mail只需要導(dǎo)入一個(gè)jar包:mail.jar。
      使用Apache Mail的時(shí)候需要導(dǎo)入兩個(gè)jar包:mail.jar、commons-email-1.3.1.jar。
      四、使用Java Mail發(fā)送郵件
    1 public static void main(String[] args) throws Exception {
    2         final String user = "779554589";
    3         final String password = "";
    4
    5         String fromAddress = "779554589@qq.com";
    6         String toAddress = "loadfate@163.com";
    7         String subject = "郵件測試主題";
    8         String content = "這是一個(gè)測試郵件<b>哈哈</b>";
    9
    10         //配置參數(shù)
    11         Properties props = new Properties();
    12         props.setProperty("mail.smtp.auth", "true");
    13         props.setProperty("mail.transport.protocol", "smtp");
    14         props.setProperty("mail.host", "smtp.qq.com");
    15         // 方法一:使用transport對象發(fā)送郵件
    16         {
    17             //通過參數(shù)生成會(huì)話
    18             Session session = Session.getInstance(props);
    19             //啟用調(diào)試模式
    20             session.setDebug(true);
    21             //創(chuàng)建一封郵件,并設(shè)置信息
    22             Message message = new MimeMessage(session);
    23             message.setFrom(new InternetAddress(fromAddress));
    24             message.setSubject(subject);
    25             message.setText(content);
    26             //創(chuàng)建傳輸
    27             Transport transport = session.getTransport();
    28             //連接smtp服務(wù)器
    29             transport.connect(user, password);
    30             //發(fā)送
    31             transport.sendMessage(message, new InternetAddress[] { new InternetAddress(toAddress) });
    32             transport.close();
    33         }
    34
    35
    36         // 方法二:使用Transport類靜態(tài)方法發(fā)送郵件
    37         {
    38             //生成Session時(shí)以獲取授權(quán)連接
    39             Session session = Session.getInstance(props, new Authenticator() {
    40                 @Override
    41                 protected PasswordAuthentication getPasswordAuthentication() {
    42                     return new PasswordAuthentication(user, password);
    43                 }
    44             });
    45             session.setDebug(true);
    46             //創(chuàng)建一封郵件,并設(shè)置信息
    47             Message message = new MimeMessage(session);
    48             message.setSubject(subject);
    49             message.setFrom(new InternetAddress(fromAddress));
    50             message.setRecipient(RecipientType.TO, new InternetAddress(toAddress));
    51             message.setContent(content, "text/html;charset=utf-8");
    52
    53             //直接發(fā)送,message通過已經(jīng)授權(quán)的Session生成
    54             Transport.send(message);
    55         }
    56     }
      五、使用Apache Mail發(fā)送郵件
    1 public class ApacheMailTest {
    2     // smtp服務(wù)器
    3     private String hostName = "smtp.qq.com";
    4     // 帳號(hào)與密碼
    5     private String userName = "779554589";
    6     private String password = "這是個(gè)秘密";
    7     // 發(fā)件人
    8     private String fromAddress = "779554589@qq.com";
    9     // 發(fā)件人姓名
    10     private String fromName = "loadfate";
    11
    12     public static void main(String[] args) throws Exception {
    13         // 收件人與收件人名字
    14         String toAddress = "loadfate@163.com";
    15         String toName = "loadfate";
    16         ApacheMailTest test = new ApacheMailTest();
    17         // 所有的異常都為處理,方便瀏覽
    18
    19         test.sendSimpleEmail(toAddress, toName);
    20         test.sendHtmlEmail(toAddress, toName);
    21         test.sendMultiPartEmail(toAddress, toName);
    22         System.out.println("發(fā)送完成");
    23     }
    24
    25     // 發(fā)送簡單郵件,類似一條信息
    26     public void sendSimpleEmail(String toAddress, String toName) throws Exception {
    27         SimpleEmail email = new SimpleEmail();
    28         email.setHostName(hostName);// 設(shè)置smtp服務(wù)器
    29         email.setAuthentication(userName, password);// 設(shè)置授權(quán)信息
    30         email.setCharset("utf-8");
    31         email.setFrom(fromAddress, fromName, "utf-8");// 設(shè)置發(fā)件人信息
    32         email.addTo(toAddress, toName, "utf-8");// 設(shè)置收件人信息
    33         email.setSubject("測試主題");// 設(shè)置主題
    34         email.setMsg("這是一個(gè)簡單的測試!");// 設(shè)置郵件內(nèi)容
    35         email.send();// 發(fā)送郵件
    36     }
    37
    38     // 發(fā)送Html內(nèi)容的郵件
    39     public void sendHtmlEmail(String toAddress, String toName) throws Exception {
    40         HtmlEmail email = new HtmlEmail();
    41         email.setHostName(hostName);
    42         email.setAuthentication(userName, password);
    43         email.setCharset("utf-8");
    44         email.addTo(toAddress, toName, "utf-8");
    45         email.setFrom(fromAddress, fromName, "utf-8");
    46         email.setSubject("這是一個(gè)html郵件");
    47         // 設(shè)置html內(nèi)容,實(shí)際使用時(shí)可以從文本讀入寫好的html代碼
    48         email.setHtmlMsg("<div style='width:100px;height:200px;'>a</div>");
    49         email.send();
    50
    51     }
    52
    53     // 發(fā)送復(fù)雜的郵件,包含附件等
    54     public void sendMultiPartEmail(String toAddress, String toName) throws Exception {
    55         MultiPartEmail email = null;
    56         email = new MultiPartEmail();
    57         email.setHostName(hostName);
    58         email.setAuthentication(userName, password);
    59         email.setCharset("utf-8");
    60         email.addTo(toAddress, toName, "utf-8");
    61         email.setFrom(fromAddress, fromName, "utf-8");
    62         email.setSubject("這是有附件的郵件");
    63         email.setMsg("<a href='#'>測試內(nèi)容</a>");
    64
    65         // 為郵件添加附加內(nèi)容
    66         EmailAttachment attachment = new EmailAttachment();
    67         attachment.setPath("D:\\郵件.txt");// 本地文件
    68         // attachment.setURL(new URL("http://xxx/a.gif"));//遠(yuǎn)程文件
    69         attachment.setDisposition(EmailAttachment.ATTACHMENT);
    70         attachment.setDescription("描述信息");
    71         // 設(shè)置附件顯示名字,必須要編碼,不然中文會(huì)亂碼
    72         attachment.setName(MimeUtility.encodeText("郵件.txt"));
    73         // 將附件添加到郵件中
    74         email.attach(attachment);
    75         email.send();
    76     }
    77 }
      六、附件
      下載地址:http://pan.baidu.com/s/1qW8rcAw
      如果失效請聯(lián)系LZ
      文件說明:
      1、maildemo.zip :maildemo的源代碼
      2、mail.jar :Java Mail的jar包
      3、commons-email-1.3.1.jar :Apache Mail的jar包

    posted @ 2014-06-11 11:19 順其自然EVO 閱讀(1007) | 評(píng)論 (0)編輯 收藏

    Loadrunner監(jiān)控服務(wù)器資源

    LoadRunner 加載監(jiān)聽服務(wù)器的步驟如下:
      1、在 LoadRunner Controller 下,將工作面板切換到 Run狀態(tài),Available Graphs 欄 ,System Resources Graphs目錄下選擇 Windows Resources,雙擊,在右側(cè)4個(gè)監(jiān)視欄中,選擇 Windows Resources-Last 60 sec雙擊,放大模塊,右鍵--> Add Measurements ,在新彈出的窗口中,添加 Monitored Server Machines 。(Add Machine 時(shí),Name 一般填機(jī)器ip),然后 ok
      2、添加完畢后,會(huì)看到監(jiān)視欄中出現(xiàn)10個(gè)性能服務(wù)器的數(shù)據(jù)條。這時(shí)需要觀察Scenario Status 的狀態(tài),如果沒有 Errors 出現(xiàn),那么過一會(huì)后,會(huì)看到 Windows Resources 欄出現(xiàn)走動(dòng)的數(shù)據(jù),表示監(jiān)聽成功;否則,出現(xiàn)了 Errors ,則說明監(jiān)聽不成功。點(diǎn)擊 紅色的 Errors ,查看失敗的原因。
      下面是我遇到的兩種錯(cuò)誤情況:
      情況1:
    Monitor name :Windows Resources. Cannot connect to machine 10.0.64.152
    Reason: 拒絕訪問。
    Hints:
    Check that your login user name appears as administrator on this machine.
    Check that you have entered the correct machine name.
    Check that the machine exists and that it is online (use the ping utility for this operation).
    Delete the machine and add it again (entry point: CFactory::Initialize). [MsgId: MMSG-47299]
      情況2:
      Monitor name :Windows Resources. Cannot connect to machine 10.0.64.152
      Reason: 找不到網(wǎng)絡(luò)路徑。
      解決方法:
      情況1的解決方法,是在網(wǎng)上找的一些方法,嘗試了較多,不知是哪一個(gè)或哪幾個(gè)生效起作用了。(后面,會(huì)總結(jié)一個(gè)統(tǒng)一的解決方法)
      情況2的解決方法:啟動(dòng)目標(biāo)服務(wù)器的 Remote Procedure Call (RPC) Locator 服務(wù),連接成功
      小結(jié)
      LoadRunner 添加 Windows監(jiān)聽器需要進(jìn)行的相關(guān)設(shè)置(下面都是對被監(jiān)視服務(wù)器的操作):
      1、共享C盤;(一般情況下,C 盤是共享狀態(tài),無需處理)
      2、保證如下服務(wù)開啟:
      a、Remote Procedure Call (RPC)
      b、Remote Procedure Call (RPC) Locator
      c、Remote Registry
      d、Workstation
      3、本地安全設(shè)置-->安裝設(shè)置-->本地策略-->安全選項(xiàng),“網(wǎng)絡(luò)訪問:本地賬戶的共享和安全模式”項(xiàng)選擇“經(jīng)典 - 本地用戶以自己的身份驗(yàn)證”;
      4、用戶需要在本地客戶端訪問服務(wù)器,操作方式,開始→運(yùn)行→輸入服務(wù)器IP地址;

    posted @ 2014-06-11 11:11 順其自然EVO 閱讀(576) | 評(píng)論 (0)編輯 收藏

    錘子便簽的Monkeyrunner 測試腳本

      MonkeyRunner可能大家已經(jīng)聽過無數(shù)次了,大家在網(wǎng)上也看過了各種關(guān)于的它的資料了,我這里就不再過多的啰嗦它的用途了,它可以對app做功能測試也可以對手機(jī)Rom做功能測試,在沒有app源碼的情況下monkeyrunner可以做到很好的功能測試。MonkeyRunner有一個(gè)錄制腳本的工具和回放的功能,大家去下載monkeyrecody.py和monkeyplayback.py這兩個(gè)腳本就可以了,這個(gè)我這里也不講了,網(wǎng)上去google可以搜到很好的教程,
      下面是我對錘子便簽的一個(gè)MonkeyRunner測試腳本。這里會(huì)用到點(diǎn)擊,拖動(dòng),截圖,截圖對比的一些方法,基本上我們寫monkeyrunner測試腳本中常調(diào)用到的方法都用到了,這里對錘子便簽測試思路是這樣的:先按照正常的操作使用步驟,一步步的操作下去,每操作一步都截圖,操作完成之后,再來對截圖進(jìn)行對比并打印出對比結(jié)果在log文本里。這里用到的是坐標(biāo)點(diǎn)的定位方法。
      #!/usr/bin/env monkeyrunner# encoding=utf-8  #導(dǎo)入python中自帶的time模塊和sys模塊,腳本中都要用到它們。import timeimport sys#MonkeyRunner自帶的三個(gè)apifrom com.android.monkeyrunner import MonkeyRunner ,MonkeyDevice ,MonkeyImage#這個(gè)函數(shù)時(shí)確認(rèn)年月日時(shí)分秒now=time.strftime("%Y-%m-%d-%H-%M-%S")#指定我們要保存圖片的位置和打印log的位置path='D:\\picture\\'logpath="D:\\log\\"#python中獲取當(dāng)前運(yùn)行的文件的名字name=sys.argv[0].split("\\")filename=name[len(name)-1]"""
      可以嘗試輸入這兩句語句就可以明白上面的兩個(gè)python方法了。
    print(name)
    print(filename)
    """#新建一個(gè)log文件log=open(logpath+filename[0:-3]+"-log"+now+".txt",'w')#連接設(shè)備,兩個(gè)參數(shù)分別是等待的時(shí)間(這里的時(shí)間都是秒為單位),設(shè)備的序列號(hào)。device=MonkeyRunner.waitForConnection(5,'b4726a2d')#安裝錘子便簽apk。參數(shù)是apk文件的位置,因?yàn)閜ython不支持中文輸入,所以在后面用了.decode('utf-8')這個(gè)方法轉(zhuǎn)碼。device.installPackage ('D:\\apk\\錘子便簽.apk'.decode('utf-8'))#打印出操作信息到log文件里log.write("安裝apk……\n")#等待2秒MonkeyRunner.sleep(2)#啟動(dòng)app,參數(shù)里是app的包名/活動(dòng)名device.startActivity(component='com.smartisan.notes/.NotesActivity')MonkeyRunner.sleep(2)#打印操作信息log.write("啟動(dòng)app……\n")#截圖result = device.takeSnapshot()#保存截圖 result.writeToFile(path+"主頁面".decode('utf-8')+now+'.png','png')#點(diǎn)擊搜索款的位置坐標(biāo)。device.touch(111,155,'DOWN_AND_UP')MonkeyRunner.sleep(2)#輸入smartisan字樣device.type("smartisan")#截圖result1=device.takeSnapshot()#保存截圖result1.writeToFile(path+"搜索框截圖".decode('utf-8')+'.png','png')#移動(dòng)第一個(gè)便簽的位置到最后面去,參數(shù)是:一個(gè)起始點(diǎn)坐標(biāo),一個(gè)終點(diǎn)坐標(biāo),移動(dòng)的時(shí)間,移動(dòng)的步驟device.drag((232,235),(216,472),3,2)MonkeyRunner.sleep(3)#截圖result2=device.takeSnapshot()#保存截圖result2.writeToFile(path+"移動(dòng)便簽".decode('utf-8')+now+".png",'png')#第一個(gè)便簽向右滑動(dòng)device.drag((109,360),(322,360))MonkeyRunner.sleep(3)#截圖result3=device.takeSnapshot()#保存截圖result3.writeToFile(path+"右移動(dòng)便簽".decode('utf-8')+now+".png",'png')#點(diǎn)擊最后一個(gè)便簽的位置device.touch(182,583,'DOWN_AND_UP')MonkeyRunner.sleep(5)#點(diǎn)擊發(fā)送的位置device.touch(324,73,'DOWN_AND_UP')MonkeyRunner.sleep(5)#點(diǎn)擊發(fā)送至長微博的位置device.touch(227,789,'DOWN_AND_UP')MonkeyRunner.sleep(5)#點(diǎn)擊生成長微博的位置device.touch(228,791,'DOWN_AND_UP')MonkeyRunner.sleep(5)#截圖result4=device.takeSnapshot()#保存圖片result4.writeToFile(path+"發(fā)長微博截圖".decode("utf-8")+now+'.png','png')#點(diǎn)擊下一步的位置device.touch(426,81,'DOWN_AND_UP')MonkeyRunner.sleep(3)#截圖result5=device.takeSnapshot()#保存截圖result5.writeToFile(path+"輸入微博賬號(hào)".decode("utf-8")+now+'.png','png')#點(diǎn)擊輸入微博賬號(hào)和密碼的幾個(gè)位置,分別輸入賬號(hào)和密碼device.touch(196,311,'DOWN_AND_UP')MonkeyRunner.sleep(3)device.type("powermo@126.com")MonkeyRunner.sleep(3)device.touch(168,378,'DOWN_AND_UP')MonkeyRunner.sleep(3)device.type("powermo1234")MonkeyRunner.sleep(3)#點(diǎn)擊登錄device.touch(237,449,'DOWN_AND_UP')MonkeyRunner.sleep(3)#截圖result6=device.takeSnapshot()#保存截圖result6.writeToFile(path+"登陸微博".decode("utf-8")+now+'.png','png')#下面就開始對之前的截圖進(jìn)行對比了#第一張截圖做對比,去文件中找到我們要對比的圖片resultTrue=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue.png')log.write("主頁面對比圖片……\n")#判斷圖片相識(shí)度是否是為90%if(result.sameAs(resultTrue,0.9)):
    #在命令行打印出信息
    print("主頁面圖片對比成功")
    #打印信息到log文件
    log.write("主頁面圖片對比成功……\n")else:
    #打印信息到命令行
    print("主頁面圖片對比失敗")
    log.write("主頁面圖片對比失敗……\n")#去文件中找到我們規(guī)定的圖片用來對比result1True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue1.png')#判斷圖片相識(shí)度是否是為90%if(result1.sameAs(result1True,0.9)):
    print("搜索框圖片對比成功")
    log.write("搜索框圖片對比成功……\n")else:
    print("搜索框圖片對比失敗")
    log.write("搜索框圖片對比失敗……\n")#對移動(dòng)便簽圖片對比result2True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue2.png')##判斷圖片相識(shí)度是否是為80%if(result2.sameAs(result2True,0.8)):
    print("移動(dòng)便簽對比成功")
    log.write("移動(dòng)便簽對比成功……\n")else:
    print("移動(dòng)便簽圖片對比失敗")
    log.write("移動(dòng)便簽對比失敗……\n")#對移動(dòng)便簽圖片進(jìn)行對比,去文件中找我們規(guī)定的圖片result3True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue3.png')##判斷圖片相識(shí)度是否是為80%if(result3.sameAs(result3True,0.8)):
    print("右移便簽圖片對比成功")
    log.write("右移便簽圖片對比成功……\n")else:
    print("右移便簽圖片對比失敗")
    log.write("右移便簽圖片對比失敗……\n")#對長微博圖片對比result4True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue4.png')if(result4.sameAs(result4True,0.8)):
    print("發(fā)長微博圖片對比成功")
    log.write("發(fā)長微博圖片對比成功……\n")else:
    print("發(fā)長微博圖片對比失敗")
    log.write("發(fā)長微博圖片對比失敗……\n")result5True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue5.png')if(result5.sameAs(result5True,0.8)):
    print("輸入微博賬號(hào)圖片對比成功")
    log.write("輸入微博賬號(hào)圖片對比成功……\n")else:
    print("輸入微博賬號(hào)圖片對比失敗")
    log.write("輸入微博賬號(hào)圖片對比失敗……\n")result6True=MonkeyRunner.loadImageFromFile('D:\\picture2\\shottrue6.png')if(result6.sameAs(result6True,0.8)):
    print("登陸微博圖片對比成功")
    log.write("登陸微博圖片對比成功……\n")else:
    print("登陸微博圖片對比失敗")
    log.write("登陸微博圖片對比失敗……\n")

    posted @ 2014-06-11 11:10 順其自然EVO 閱讀(284) | 評(píng)論 (0)編輯 收藏

    LinkedIn的軟件測試生命周期

      在LinkedIn,質(zhì)量是產(chǎn)品發(fā)布的看門人。上周,我們告訴了大家測試前沿,LinkedIn的web框架。今天,我們將帶您看看我們的測試生命周期。
      如果我們按時(shí)交貨,但產(chǎn)品有缺陷,還是證明我們沒有按時(shí)交付。——Philip Crosby
      測試生命周期
      看看在LinkedIn中測試生命周期是什么樣子的:
      1.需求收集
      產(chǎn)品團(tuán)隊(duì)定義了功能需求和設(shè)計(jì)者創(chuàng)建的線框圖。在設(shè)計(jì)和產(chǎn)品需求文檔(PRD)被創(chuàng)建后,一切都涉及到整個(gè)團(tuán)隊(duì),包括開發(fā)人員和測試工程師。
      2.測試計(jì)劃
      在生命周期的下一步是對產(chǎn)品或功能的所有測試,進(jìn)行計(jì)劃,包括:
      創(chuàng)建測試計(jì)劃
      編寫測試用例
      按高、中或低的順序進(jìn)行優(yōu)先測試用例,這樣他們可以基于項(xiàng)目的范圍運(yùn)行
      舉行一個(gè)測試計(jì)劃和測試用例評(píng)審會(huì)議,以確保溝通和充分理解測試范圍
      3.功能測試
      功能測試和回歸測試在測試計(jì)劃完成后開始。這個(gè)測試包括:
      新功能測試:瀏覽器兼容性測試,使用VMWare(Firefox、Safari、Chrome、IE)。
      Bug生命周期:在JIRA提交Bug。對bugs進(jìn)行修復(fù)和驗(yàn)證。
      回歸測試:確保沒有任何現(xiàn)功能壞了(即:不可用)。我們使用自動(dòng)化測試用例組進(jìn)行測試。
      A / B測試:我們一步一步來發(fā)布功能。首先發(fā)布到內(nèi)部組織,然后是公司,所以我們要捕獲所有邊界情況。畢竟錯(cuò)誤是固定的,我們會(huì)慢慢傾斜于我們的用戶。
      4.自動(dòng)化
      自動(dòng)化是并行在功能測試中完成的。我們使用 Selenium with Ruby進(jìn)行UI自動(dòng)化和Selenium with Java進(jìn)行移動(dòng)版自動(dòng)化。單元測試也為新功能而寫。在LinkedIn,我們發(fā)布一個(gè)新特性后,100%自動(dòng)化時(shí)間表就相應(yīng)計(jì)算出來了。
      5.回歸運(yùn)行和CI
      我們創(chuàng)建一個(gè)持續(xù)集成(CI)在Hudson上運(yùn)行,開始單元測試運(yùn)行和自動(dòng)化的回歸測試用例集。為了一個(gè)分支通過“GO”的標(biāo)準(zhǔn),它必須在上述所有取得成功。

    6.發(fā)布分支的創(chuàng)建
      分支的特性確認(rèn)合格后,與所有其他功能分支合并發(fā)布。執(zhí)行回歸測試和功能測試分支的發(fā)布,以確保分支合并之間的兼容性。
      7.部署和測試
      接著,發(fā)布分支被部署到交付的準(zhǔn)備環(huán)境。執(zhí)行完整性測試,用不同的措施來保證向后兼容的代碼被推為應(yīng)用程序和服務(wù)。所有發(fā)現(xiàn)的問題都需要修復(fù)以確保順利部署。測試工程師進(jìn)行最后一輪回歸和特性測試,開發(fā)人員需要查看日志。
      8.性能測試
      我們的性能團(tuán)隊(duì)要進(jìn)行JMeter測試,確保功能可以在工作中正常負(fù)載。這些測試在測試環(huán)境上運(yùn)行,1/8th 的生產(chǎn)負(fù)荷。
      9.產(chǎn)品推進(jìn)
      我們密切關(guān)注代碼,使其生產(chǎn)方式,確保交付出去的代碼具有良好的質(zhì)量。這幾乎是可以慶祝的事。
      10.監(jiān)控
      我們的工作還沒有完成。我們還需要不斷地通過監(jiān)控日志和實(shí)時(shí)圖表,以確保一切都順利工作。
      11.補(bǔ)丁(如果需要)
      功能運(yùn)用生產(chǎn)環(huán)境中后,我們的客戶服務(wù)團(tuán)隊(duì)、產(chǎn)品團(tuán)隊(duì)和工程師會(huì)不斷地從我們的網(wǎng)站會(huì)從反饋工具中監(jiān)控到所有客戶的反饋。如果有任何問題,我們試圖盡快修復(fù)它們。在大多數(shù)情況下,會(huì)在24小時(shí)內(nèi)修復(fù)。這被稱為hotfixing bug。
      在LinkedIn的測試工作
      我們的目標(biāo)是,在LinkedIn中,發(fā)揮產(chǎn)品的可用性,提供最優(yōu)質(zhì)的產(chǎn)品。作為測試工程師,我可以得到一個(gè)良好的睡眠,你要知道在LinkedIn中永遠(yuǎn)不會(huì)在任何環(huán)節(jié)對質(zhì)量進(jìn)行妥協(xié)。
      Quality is never an accident; It is always the result of intelligent effort. -- John Ruskin
      質(zhì)量從來不是偶然的,它總是聰明努力的結(jié)果。——約翰·拉斯金

    posted @ 2014-06-11 11:09 順其自然EVO 閱讀(162) | 評(píng)論 (0)編輯 收藏

    僅列出標(biāo)題
    共394頁: First 上一頁 101 102 103 104 105 106 107 108 109 下一頁 Last 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 国产亚洲精品免费| 一区二区三区观看免费中文视频在线播放 | 亚洲av成人中文无码专区| 亚洲自偷精品视频自拍| 日韩a毛片免费观看| h在线观看视频免费网站| 中文字幕亚洲无线码a| 国产成人精品久久亚洲高清不卡| 免费精品久久久久久中文字幕 | 久久精品女人天堂AV免费观看| 国产免费直播在线观看视频| 精品亚洲成AV人在线观看| 国产大片免费天天看| 四虎免费久久影院| 亚洲自偷自偷在线成人网站传媒| 国产亚洲欧美在线观看| 日本免费网址大全在线观看| 亚洲国产女人aaa毛片在线| 一个人免费观看日本www视频| 小日子的在线观看免费| 中文字幕精品亚洲无线码二区 | 96免费精品视频在线观看| 亚洲午夜久久久影院| 老司机福利在线免费观看| 噼里啪啦电影在线观看免费高清| 又黄又爽无遮挡免费视频| 亚洲免费视频观看| 99久久久国产精品免费牛牛| 亚洲乱色熟女一区二区三区丝袜 | 无限动漫网在线观看免费| 久久精品亚洲一区二区三区浴池| 日韩成人精品日本亚洲| 毛片高清视频在线看免费观看| 中文字幕精品亚洲无线码一区| 亚洲五月综合缴情婷婷| 57pao国产成永久免费视频| 亚洲AV无码精品色午夜果冻不卡| 亚洲AV无码一区二区一二区| 猫咪社区免费资源在线观看| 亚洲欧洲日韩国产一区二区三区| 男女一边摸一边做爽的免费视频|