一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

進化的測試 軟件測試,自動化測試,白盒測試,Python

 liuchangxin81 2014-05-13
 

用Selenium實現(xiàn)自動化測試的過程中,如果選擇頁面上的元素并且對之進行各種操作,是一個常見的任務(wù)。Selenium提供了多種定位方法:

  • id:最有效、最方便的方法
  • name:跟id類似的
  • class name:對某些具有相同類的元素一網(wǎng)打盡的好方法
  • link text 和 partial link text: 用在定位超鏈接上比較多
  • tag name:與class name有點類似
  • css selector:如果你試用jQuery,這個一定是你喜歡的方法
  • xpath:。。。 /html/body/div/div[2]/div[2]/div[2]/div[5]/div/p[2]

網(wǎng)上很多Selenium的介紹文章,在講述如何利用XPath定 位元素的時候,通常都是這樣子說的“打開Firefox瀏覽器,安裝Firebug插件,然后就能方便地獲得該元素的XPath了”。由于不求甚解,在一 段時間內(nèi)我真以為這些看起來沒什么意義,中間穿插著各種數(shù)組操作,讀起來反人類反社會的所謂XPath就是真的XPath,同志們大家都被誤導(dǎo)了。

什么是XPath:http://www./TR/xpath/
XPath基礎(chǔ)教程:http://www./xpath/default.asp

XPath在Selenium測試中有好些缺點:1. 性能差,定位元素的性能比起大多數(shù)其他方法要差;2. 不夠健壯,XPath會隨著頁面元素布局的改變而改變;3. 兼容性不好,在不同的瀏覽器下對XPath的實現(xiàn)是不一樣的。如此多的弱點,為什么它還存在于Selenium中呢?Selenium提供了這7個元素定 位的工具,就好像工具箱里面有錘子有老虎鉗有螺絲刀,每個工具都能完成特定的任務(wù),前提是要在正確的前提下,正確地使用。

XPath通常會在如下場景:一個寫自動化測試的人,發(fā)現(xiàn)他想要操作的元素不能通過id, name, link text等比較方便有效的方法來進行定位,苦逼的他沒能說服開發(fā)這個頁面的人把他想要的id加上,他開始用所謂的XPath來定位元素,代碼中充滿了各種 讓人摸不著頭腦的XPath(/html/body/div/div[3]/div[2]/div[4]/p[2]),在我看來這樣的代碼跟錄制出來的腳 本沒有任何區(qū)別。可讀性差,幾乎不能維護。XPath理論上可以這樣使用,但是實際上應(yīng)該避免這樣的使用。

XPath的一些優(yōu)點是大家需要知道的,例如:1. XPath可以通過某個元素找到它的祖先(Ancestors);2. 可以做布爾邏輯判斷,例如/button[@value=’submit’ or @name=’tijiao’]

回到上面的場景,假如說那個苦逼的人想定位到頁面上的一個提交按鈕,這個按鈕不能通過id或者name來定位。這個時候他要做的事情不是打開 Firebug定位提交按鈕右擊鼠標(biāo)再點“Copy XPath”。而是應(yīng)該是找開發(fā)把id或者name加上。如果不行,解決思路可以是:1. 找到該按鈕的特征,例如按鈕的文字是 submit;2. 用XPath定位,可以這樣寫://button[@value='submit']。

我個人對使用XPath比較反感的,如果可能的話,盡可能使用id或者name。真的要用XPath,千萬千萬不要打開Firebug定位提交按鈕右擊鼠標(biāo)再點“Copy XPath”。 先認真學(xué)習(xí)XPath,后使用。在很長一段時間里面,我對XPath真的是恨之入骨,恨不得先殺之而后快,但是想到存在就是合理,那么多大牛們都沒有把 XPath摒棄與Selenium之外,XPath必然有它的價值。最近花了點時間學(xué)習(xí)了一下XPath,并且讀了一些關(guān)于如何在Selenium里面正 確使用XPath的文章,豁然開朗。

參考文章:

232011
 

這玩意兒網(wǎng)上很多,但是坑更多,現(xiàn)在記錄一個肯定能用的。

我的環(huán)境是Python 2.6 + Selenium 2.6

from selenium import webdriver
profile = webdriver.FirefoxProfile()
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.http', 'proxy_url')
profile.set_preference('network.proxy.http_port', 3128)
profile.set_preference('network.proxy.ssl', 'proxy_url')
profile.set_preference('network.proxy.ssl_port', 3128)
profile.update_preferences()
driver = webdriver.Firefox(profile)

這些坑分別是:

有些地方只告訴你配置network.proxy.http和network.proxy.http_port。但是如果不設(shè)置network.proxy.type,一切都是浮云。這個配置是個整數(shù),默認是0,就是直接連接;1就是手工配置代理。
profile.set_preference(‘network.proxy.type’, 1)

那個端口號3128是整數(shù)
profile.set_preference(‘network.proxy.http’, ‘proxy_url’)
profile.set_preference(‘network.proxy.http_port’, 3128)

如果有些資源是https的,是需要另外配置network.proxy.ssl和network.proxy.ssl_port的。例如facebook的圖片。。。

set完以后,是需要update_preferences的。。。
profile.update_preferences()

最后貼一個完整的Firefox配置參數(shù)表:http://kb./Firefox_:_FAQs_:_About:config_Entries

如果發(fā)現(xiàn)自己的配置好像沒有生效,那么在webdriver啟動的Firefox里面輸入about:config。然后對著上面那個配置參數(shù)表來看??倳l(fā)現(xiàn)掉哪個坑的。

272011
 

之前介紹過如何使用TestNG來驅(qū)動WebDriver,用Ant來自動化運行測試。今天分享一下如何把這些東西都放到HudsonJenkins也行)里面呢?

Hudson是一個比較流行都持續(xù)集成工具。用Hudson來驅(qū)動自動化測試的好處有以下這些:

  • 類似crontab的自動任務(wù)管理
  • 豐富的插件支持
  • 支持分布式任務(wù)
  • 容易部署

其實整個過程很簡單,把Hudson跑起來,新建一個Job,配置一下Ant任務(wù)就好了。這里只分享一下我遇到的一些坑。

是否使用Source Code Management獲取最新的測試代碼?

如果每次測試都拉最新的代碼,好處就是保證測試代碼是最新的。但是也會帶來一些問題,測試代碼本身也是代碼,怎么保證最新的測試代碼沒有問題呢?我個人認為,如果團隊比較小,可以直接拉最新的代碼;如果團隊大,需要控制。

如果不用SCM插件,怎么樣更新自動化測試代碼?

我想到的一種辦法就是,在Hudson里面建立一個構(gòu)建自動化測試代碼的Job,這個Job的產(chǎn)物就是自動化測試的包,譬如說如果用 WebDriver或者Selenium,就把測試代碼build成一個或者若干個jar包,然后建立一個latest的軟鏈接指向最新的jar包;在運 行自動化測試的Job里面做好配置,運行測試的目標(biāo)jar包就指向latest.jar就OK了。

TestNG的結(jié)果如何跟Hudson整合

Hudson插件很多,可以用testng-plugin來完成這個任務(wù)。配置比較簡單,在Ant腳本里面配置好TestNG的result output,然后在Hudson里面把測試報告的模式填好。我直接填的TestNG的默認結(jié)果文件“testng-results.xml”。build.xml節(jié)點配置的一個例子:

    <target name="live_check" depends="compile,remove_last_result">
        <testng outputdir="${testng.output.dir}" classpathref="classes" delegateCommandSystemProperties="true" useDefaultListeners="true">
            <xmlfileset dir="${base.dir}" includes="${live.check.config}"/>
        </testng>
        <move file="${testng.output.dir}/${test.result.file}" todir="${ci.workspace}"/>
    </target>

首先在testng節(jié)點指定outputdir屬性,然后測試運行完成以后把結(jié)果文件移動到Hudson的workspace

怎么樣把Ant的參數(shù)傳遞給TestNG

很多時候我們會希望通過ant把一些參數(shù)傳遞給testng.xml,從而使得測試更加靈活。例如傳遞不用的base_url可以測試不同的站點。還有配置不同的瀏覽器。雖然之前這篇文章已經(jīng)介紹了如何把Ant的參數(shù)傳遞給TestNG, 但是那個方法有個缺點,如果在測試方法A里面調(diào)用了測試方法B,測試方法B是不能拿到Ant傳進去的參數(shù)的。我的辦法比較土,就是首先寫好一個 testng_base.xml的模板文件,把一些可能經(jīng)常改變的數(shù)值替換成參數(shù),然后用Ant的replace任務(wù)做字符串替換。

    <target name="replace_testng_xml">
        <replace file="${base.dir}/${testng.file}" token="@@base_url@@" value="${base_url}"/>
        <replace file="${base.dir}/${testng.file}" token="@@browser@@" value="${webdriver.browser}"/>
    </target>
232011
 

UI自動化測試其實并不是那么穩(wěn)定,可能是因為UI元素的改動,也可能是因為網(wǎng)絡(luò)的不穩(wěn)定,在測試失敗的時 候,WebDriver通常會拋出一些異常;通過異常信息通常都能知道大概是哪里出錯了,但是如果能加上截屏,那就更加好了。尤其是用Remote WebDriver運行測試,所有測試都是通過Selenium Grid分發(fā)到各個節(jié)點來運行,不同節(jié)點的配置還有可能不是完全一樣。

如果是使用RemoteWebDriver的話,它提供了一個很好的功能,就是會把運行測試發(fā)生異常時候的截圖也放到異常里面,具體可以參考RemoteWebDriver的簡介。代碼很簡單:

public String extractScreenShot(WebDriverException e) {
    Throwable cause = e.getCause();
    if (cause instanceof ScreenshotException) {
        return ((ScreenshotException) cause).getBase64EncodedScreenshot();
    }
    return null;
}

怎么樣才能在異常發(fā)生的時候自動把異常抓住呢?簡單來說就是要對寫測試代碼的人是透明了,在寫測試代碼的時候不需要特別去處理異常。這里需要實現(xiàn) WebDriverEventListener接口,然后把RemoteWebDriver對象和實現(xiàn)WebDriverEventListener接口 的對象包到一起,實例化一個EventFiringWebDriver對象。之后的事情就跟用一個普通的RemoteWebDriver對象沒有任何區(qū) 別。

實現(xiàn)WebDriverEventListener接口的一個例子:

public class MyEventListener implements WebDriverEventListener {
    public void onException(Throwable ex, WebDriver arg1) {
        String filename = generateRandomFilename(ex);
        try {
            byte[] btDataFile = Base64.decodeBase64(extractScreenShot(ex).getBytes());
            File of = new File(filename);
            FileOutputStream osf = new FileOutputStream(of);
            osf.write(btDataFile);
            osf.flush();
            osf.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    private String generateRandomFilename(Throwable ex) {
        Calendar c = Calendar.getInstance();
        String filename = ex.getMessage();
        int i = filename.indexOf('\n');
        filename = filename.substring(0, i).replaceAll("\\s", "_")
                    .replaceAll(":", "")
                    + ".png";
                    filename = "" + c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH)
                    + "-" + c.get(Calendar.DAY_OF_MONTH) + "-"
                    + c.get(Calendar.HOUR_OF_DAY) + "-" + c.get(Calendar.MINUTE)
                    + "-" + c.get(Calendar.SECOND) + "-" + filename;
        return filename;
    }
 
    private String extractScreenShot(Throwable ex) {
        Throwable cause = ex.getCause();
        if (cause instanceof ScreenshotException) {
            return ((ScreenshotException) cause).getBase64EncodedScreenshot();
        }
        return null;
    }
 
    @Override
    public void afterChangeValueOf(WebElement arg0, WebDriver arg1) {
    // TODO Auto-generated method stub
 
    }
}

實例化一個EventFiringWebDriver對象:

@Test
public void setup(){
    String remote_driver_url = "http://localhost:4444/wd/hub";
    DesiredCapabilities capability = null;
    capability = DesiredCapabilities.firefox();
    WebDriverEventListener eventListener = new MyEventListener();
    WebDriver driver = new EventFiringWebDriver(new RemoteWebDriver(new URL(
                    remote_driver_url), capability)).register(eventListener);
}

之后如果測試遇到任何異常,都會在basedir(這個是要自己配置的)下面生成一個類似這樣的png截圖(2011-7-22-20-55-9- Element_is_not_currently_visible_and_so_may_not_be_interacted_with.png)。

這些代碼段演示了如何使用WebDriverEventListener接口以及EventFiringWebDriver類,實現(xiàn)監(jiān)聽測試中所拋出的異常,并且把異常里面附帶的截圖保存為png文件。

參考博客:Generating a screen capture on exception thrown with Selenium 2

202011
 

Selenium 2 已經(jīng)發(fā)布了一個多月,官方版本已經(jīng)到了Selenium 2.3,并且在Google code里面可以找到2.4的 下載。Selenium 2 最大的更新就是集成了WebDriver。這兩者是什么關(guān)系呢?如果你搜索WebDriver,第一條結(jié)果是Selenium。其實WebDriver和 Selenium可以說是在實現(xiàn)UI Automation的競爭對手。Selenium是運行在JavaScript的sandbox里面,所以很容易就支持不同的瀏覽器;而 WebDriver則是直接操作瀏覽器本身,更接近用戶的真實操作,但正因為如此,所以WebDriver在多瀏覽器/操作系統(tǒng)的支持上就要落后于 Selenium。不過從Selenium 2開始,這兩個項目合并了,可以繼續(xù)用原來的Selenium,也可以考慮遷移到WebDriver。我個人認為WebDriver應(yīng)該是以后的大趨勢, 還是值得遷移的。至于你信不信,我反正是信了。

作為一個輕量級的UI Automation框架,需要寫一些驅(qū)動它的代碼,大部分人會選擇JUnit,因為JUnit是單元測試的事實標(biāo)準(zhǔn);但是我會用TestNG。這些UI Automation的東西,它們本身不是單元測試,而且也沒有太多單元測試的風(fēng)格。

從一段簡單的測試開始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class GoogleTest  {
    @Test
    public void search(ITestContext context) {
        WebDriver driver = new FirefoxDriver();
 
        driver.get("http://www.google.com");
 
        WebElement element = driver.findElement(By.name("q"));
 
        element.sendKeys("magus");
        element.submit();
 
        Assert.assertTrue(driver.getTitle().contains("magus"), "Something wrong with title");                           
    }
}

TestNG應(yīng)用了Java的Annotations,只需要在測試方法上面打上@Test就可以標(biāo)示出search是一個測試方法。用TestNG運行測試還需要一個testng.xml的文件,文件名其實可以隨便起,沒有關(guān)系的。

1
2
3
4
5
6
7
8
9
10
11
<suite name="Magus demo" verbose="2">
    <test name="Search function">
        <classes>
            <class name="test.GoogleTest">
                <methods>
                    <include name="search" />
                </methods>
            </class>
        </classes>
    </test>
</suite>

我想讓測試更加靈活,1. 可以配置使用任意支持的瀏覽器進行測試;2. 配置所有Google的URL;3. 配置搜索的關(guān)鍵字。修改后的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class GoogleTest  {
    WebDriver driver;
 
    @Parameters({"browser"})
    @BeforeTest
    public void setupBrowser(String browser){
        if (browser.equals("firefox")){
            driver = new FirefoxDriver();
        } else {
            driver = new ChromeDriver();
        }   
    }   
 
    @Parameters({ "url", "keyword" })
    @Test
    public void search(String url, String keyword, ITestContext context) {        driver.get(url);
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys(keyword);
        element.submit();
        Assert.assertTrue(driver.getTitle().contains(keyword), "Something wrong with title");        }   
}

testng.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<suite name="Magus demo" verbose="2">
    <parameter name="browser" value="firefox" />
    <parameter name="url" value="http://www.google.com" />
    <parameter name="keyword" value="magus" />
    <test name="Search function" preserve-order="true">
        <classes>
            <class name="test.GoogleTest">
                <methods>
                    <include name="setupBrowser" />
                    <include name="search" />
                </methods>
            </class>
        </classes>
    </test>
</suite>

利用TestNG的@Parameters標(biāo)簽,讓測試方法從testng.xml里面讀取參數(shù),實現(xiàn)參數(shù)化。在testng.xml的配置 中,test節(jié)點需要增加一個屬性的配置: preserve-order=”true”。這個preserve-order默認是false,在節(jié)點下面的所有方法的執(zhí)行順序是無序的。把它設(shè)為true以后就能保證在節(jié)點下的方法是按照順序執(zhí)行的。TestNG的這個功能可以方便我們在testng.xml里面拼裝測試。假設(shè)我們有很多獨立的測試方法,例如

  • navigateCategory
  • addComment
  • addFriend
  • login
  • logout

就可以在testng.xml里面拼出不同的測試,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<test name="Add friend" preserve-order="true">
    <classes>
        <class name="test.GoogleTest">
            <methods>
                <include name="login" />
                <include name="addFriend" />
                <include name="logout" />
            </methods>
        </class>
    </classes>
</test>
<test name="Add comment to category" preserve-order="true">
    <classes>
        <class name="test.GoogleTest">
            <methods>                <include name="login" />
                <include name="navigateCategory" />
                <include name="addComment" />
                <include name="logout" />
            </methods>
        </class>
    </classes>
</test>

TestNG比JUnit更加適合做一些非單元測試的事情,不是說JUnit不好,而是不能把JUnit當(dāng)成萬能的錘子,到處釘釘子。WebDriver的API比Selenium的更加簡潔,會是以后的大趨勢。

之后打算分享一下如何用ant把自動化測試自動化起來。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日本丰满大奶熟女一区二区| 麻豆最新出品国产精品| 欧美精品女同一区二区| 日本加勒比在线播放一区| 熟女高潮一区二区三区| 久久精品国产99精品亚洲| 91久久精品国产成人| 丰满少妇被粗大猛烈进出视频| 亚洲男人的天堂久久a| 好吊日视频这里都是精品| 国产又大又硬又粗又湿| 久久热这里只有精品视频| 一区二区三区国产日韩| 千仞雪下面好爽好紧好湿全文| 国产伦精品一区二区三区高清版| 国产一区国产二区在线视频| 视频一区二区三区自拍偷| 国产精品丝袜美腿一区二区| 少妇丰满a一区二区三区| 成人免费在线视频大香蕉| 在线观看免费午夜福利| 又黄又爽禁片视频在线观看| 亚洲精品熟女国产多毛| 日本加勒比不卡二三四区| 一区中文字幕人妻少妇| 精品人妻一区二区四区| 国产又大又黄又粗又免费| 中文字幕人妻综合一区二区| 丝袜诱惑一区二区三区| 美女露小粉嫩91精品久久久| 好骚国产99在线中文| 免费大片黄在线观看日本| 成人区人妻精品一区二区三区| 欧美大粗爽一区二区三区| 久久热在线视频免费观看| 久久天堂夜夜一本婷婷| 国产成人精品视频一二区| 美国黑人一级黄色大片| 美女极度色诱视频在线观看| 婷婷开心五月亚洲综合| 精品视频一区二区三区不卡|