飞书上点链接怎么指定跳转浏览器_链接示例表功能还可以这样用??
在 CukeTest 最新版 1.6.0 中更新了一個(gè)新功能——鏈接示例表,能夠?qū)⑼獠烤S護(hù)的測(cè)試用例數(shù)據(jù)文件直接鏈接到示例表中使用。
了解行為驅(qū)動(dòng)(BDD)或Cucumber的同學(xué)都知道,長(zhǎng)久以來(lái),Cucumber里面的場(chǎng)景大綱可以通過(guò)內(nèi)嵌的數(shù)據(jù)表來(lái)驅(qū)動(dòng)。這也意味著每次修改數(shù)據(jù)需要手動(dòng)編輯feature文件,改動(dòng)示例表的數(shù)據(jù)。在持續(xù)集成越來(lái)越普及的今天,很多用戶傾向于將數(shù)據(jù)獨(dú)立維護(hù)。因此原來(lái)內(nèi)嵌feature文件的方式會(huì)有使用上的不便。上述的新功能是針對(duì)BDD/Cucumber的重要革新,解決了數(shù)據(jù)維護(hù)使用上的問(wèn)題。
同時(shí)它的出現(xiàn)使得場(chǎng)景大綱這一自動(dòng)化測(cè)試常用的概念獲得了更廣泛的能力——使用動(dòng)態(tài)數(shù)據(jù)驅(qū)動(dòng)自動(dòng)化操作:當(dāng)你需要增刪自動(dòng)化操作時(shí),只需要修改外部的表格文件即可,無(wú)需修改任何代碼或feature文件。
那么首先讓我們簡(jiǎn)單了解一下鏈接示例表在測(cè)試用例方面的應(yīng)用,然后再來(lái)了解如何使用鏈接示例表的自動(dòng)化操作管理能力吧!
示例表如何作用于測(cè)試
示例表是場(chǎng)景大綱的數(shù)據(jù)部分,由于場(chǎng)景大綱適合用于這樣的場(chǎng)景:測(cè)試中需要大量同樣的操作來(lái)驗(yàn)證在被測(cè)應(yīng)用中的結(jié)果是否正確。比如針對(duì)登錄、注冊(cè)界面的后端校驗(yàn)數(shù)據(jù)。這樣的場(chǎng)景如果使用常規(guī)的場(chǎng)景和步驟來(lái)實(shí)現(xiàn),需要寫(xiě)非常多重復(fù)的內(nèi)容,維護(hù)起來(lái)也相當(dāng)?shù)馁M(fèi)力。以一個(gè)簡(jiǎn)單的加法場(chǎng)景說(shuō)明,將加號(hào)兩邊的數(shù)字以及預(yù)期加法結(jié)果放到示例表中,代碼中計(jì)算兩數(shù)之和,再與預(yù)期結(jié)果相比較。那么示例表呈現(xiàn)如下效果:
示例表而其對(duì)應(yīng)的場(chǎng)景大綱定義如下:
場(chǎng)景大綱在項(xiàng)目運(yùn)行時(shí),表中的每一行數(shù)據(jù)都會(huì)作為參數(shù)與場(chǎng)景大綱組合成一個(gè)場(chǎng)景,比如以上示例表中共有三行數(shù)據(jù),運(yùn)行時(shí)就會(huì)解析為三個(gè)場(chǎng)景來(lái)運(yùn)行,部分報(bào)告截圖如下:
場(chǎng)景大綱運(yùn)行結(jié)果運(yùn)行結(jié)果中有一個(gè)場(chǎng)景發(fā)生了錯(cuò)誤,是因?yàn)槭纠碇械谌斜旧淼臄?shù)據(jù)就是無(wú)法通過(guò)測(cè)試的,即反面用例。
在先前的 CukeTest 版本中,示例表已經(jīng)支持編輯以及數(shù)據(jù)的導(dǎo)入導(dǎo)出,但仍然不足以滿足用戶的某些需求,比如擁有大量不同常見(jiàn)的測(cè)試用例表的情況,需要反復(fù)的導(dǎo)入新的數(shù)據(jù)。而現(xiàn)在,只要改用鏈接示例表就可以滿足這些需求了!
將鏈接示例表用于 Web 自動(dòng)化測(cè)試
下面我們將鏈接示例表用于 Web 測(cè)試,被測(cè)應(yīng)用是一個(gè)簡(jiǎn)單的網(wǎng)上點(diǎn)單頁(yè)面,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的點(diǎn)單功能驗(yàn)證,場(chǎng)景與步驟的定義如下:
# language: zh-CN功能: 網(wǎng)上點(diǎn)單
使用https://cuketest.github.io/apps/shopping-cart/ 進(jìn)行在線點(diǎn)單的自動(dòng)化
場(chǎng)景: 訪問(wèn)鏈接
假如跳轉(zhuǎn)到"https://cuketest.github.io/apps/shopping-cart/"
場(chǎng)景大綱: 點(diǎn)單
當(dāng)選擇容量""
那么單價(jià)是否為""
那么購(gòu)買(mǎi)份
例子:
#data_source: support\web.csv
場(chǎng)景: 驗(yàn)證購(gòu)物車(chē)總價(jià)
當(dāng)讀取csv文件"features/support/web.csv"并計(jì)算總價(jià)
那么驗(yàn)證購(gòu)物車(chē)的總價(jià)
那么關(guān)閉瀏覽器
您應(yīng)該注意到,對(duì)于普通的場(chǎng)景大綱而言,數(shù)據(jù)是嵌入在feature文件里的。而這里,我們使用了“#data_source: support\web.csv”直接引用了這個(gè)csv文件,而這個(gè)web.csv文件的內(nèi)容如下:
category, capacity, count, priceScotch.io Signature Lager, 30 Pack, 2, 19.99
Scotch.io Signature Lager, 40oz Bottle, 1, 4.99
Scotch.io Signature Lager, 6 Pack, 4, 12.99
通過(guò)鏈接到外部文件作為示例表,能夠非常靈活的進(jìn)行用例管理。步驟定義的代碼如下:
const?assert?=?require('assert');const?{?Util?}?=?require('leanpro.common');
var?{?Given,?When,?Then?}?=?require('cucumber');
const?{driver}?=?require('../support/web_driver');
const?{By}?=?require("selenium-webdriver")
Given("跳轉(zhuǎn)到{string}",?async?function?(url)?{
????await?driver.get(url);
});
When("選擇容量{string}",?async?function?(capacity)?{
????driver.findElement({css:'select'}).click();
????//?xpath選擇器定位內(nèi)容為capacity的option標(biāo)簽
????driver.findElement({?xpath:?`//option[text()="${capacity}"]`}).click();
});
Then("單價(jià)是否為{string}",?async?function?(price)?{
????let?value?=?await?driver.findElement({?css:".flux-product-detail?.price"}).getText();
????assert.strictEqual(value.slice(8),?price);
});
Then("購(gòu)買(mǎi){int}份",?async?function?(count)?{
????for(let?i=0;?i????????await?driver.findElement({?xpath:?'//button[text()="Add?To?Cart"]'}).click();
????}
});
When("讀取csv文件{string}并計(jì)算總價(jià)",?async?function?(filePath)?{
????let?table?=?await?Util.loadCsvFile(filePath);
????let?total?=?0;
????table.forEach(row?=>{
????????let?count?=?parseInt(row.count,?10);
????????let?price?=?parseFloat(row.price);
????????total?+=?count?*?price;
????})
????this.total?=?total;
});
Then("驗(yàn)證購(gòu)物車(chē)的總價(jià)",?async?function?()?{
????let?cartTotal?=?await?driver.findElement({?className:"total"}).getText();
????this.attach(`購(gòu)物車(chē)總價(jià)為:?${cartTotal}`)
????assert.strictEqual(this.total,?parseFloat(cartTotal.slice(8)));
});
Then("關(guān)閉瀏覽器",?async?function?()?{
????driver.quit();
});
這里用到了兩次 xpath 選擇器的text()方法,能夠找到指定內(nèi)容的元素,非常適合配合用例中比較易讀的數(shù)據(jù)形式,比如在本次的場(chǎng)景中,要修改下拉框中不同的容量,那么在樣例中,相比與維護(hù)選中第 N 個(gè)容量,還是直接維護(hù)容量的規(guī)格更合適,因?yàn)榱斜淼捻樞蛟诤芏鄷r(shí)候都是不夠可靠的。特別是針對(duì)、
、這種通常可用的其它屬性不豐富的標(biāo)簽。本個(gè)例子中驗(yàn)證的是點(diǎn)單功能,如果讀者有興趣可以復(fù)制源碼,自行嘗試一下驗(yàn)證庫(kù)存功能。這里為了用戶復(fù)制方便,直接使用了feature文件的源碼。實(shí)際使用時(shí),在CukeTest中可以在可視化視圖中通過(guò)點(diǎn)擊,直接添加鏈接示例表。
將鏈接示例表用于內(nèi)容爬取
CukeTest 作為一個(gè)自動(dòng)化測(cè)試的開(kāi)發(fā)工具,也能夠適用于很多其它的自動(dòng)化場(chǎng)景,在結(jié)合鏈接示例表以后,其能夠覆蓋的場(chǎng)景更多了,并且更加的實(shí)用了。下面我們同樣以建立內(nèi)容聚合平臺(tái)的自動(dòng)爬取為例,(參考?xì)v史文章:教你搭建自己的內(nèi)容聚合網(wǎng)站)。相信還有部分讀者對(duì)它使用 Puppeteer 搭建內(nèi)容聚合平臺(tái)的文章有印象,這次我們換 Selenium 為引擎,實(shí)現(xiàn)自動(dòng)抓取指定網(wǎng)站中的搜索結(jié)果。
相比于之前那篇文章的實(shí)現(xiàn),加入鏈接示例表后,爬取的網(wǎng)站不再需要在feature代碼中維護(hù),而是直接在數(shù)據(jù)文件中添加網(wǎng)站鏈接即可。
先讓我們來(lái)看一下鏈接示例表的.csv文件:
抓取網(wǎng)站的 csv需要注意的是search_url這一列,其中的%s作為搜索關(guān)鍵詞的占位符,場(chǎng)景運(yùn)行中會(huì)替換為完整的搜索鏈接,直接跳轉(zhuǎn)到搜索結(jié)果的頁(yè)面。(使用%s作為搜索關(guān)鍵詞的占位符的語(yǔ)法借鑒了 Chrome 創(chuàng)建自定義搜索引擎的語(yǔ)法,感興趣的讀者可以了解一下。)
接著是title_selector跟title_url_selector兩列,前者是找每條搜索結(jié)果的元素,后者找解析搜索結(jié)果中的標(biāo)題(通常也是指向搜索結(jié)果的鏈接)。這種先找大塊的內(nèi)容,再解析每一塊內(nèi)容得到想要的數(shù)據(jù),是爬蟲(chóng)常用的一種技巧。
通過(guò)這樣的一張表,很好的將爬蟲(chóng)管理了起來(lái),對(duì)于大部分的網(wǎng)站都?jí)蛴昧?#xff0c;下面讓我們看看如何針對(duì)這張表定義場(chǎng)景跟步驟描述:
# language: zh-CN@scrap
功能: 抓取視頻和文章
使用示例表來(lái)進(jìn)行視頻文章的抓取(以嗶哩嗶哩與掘金為例)
場(chǎng)景大綱: 抓取并保存在本地
當(dāng)正在抓取""網(wǎng)站
那么搜索關(guān)鍵詞""由""
那么使用選擇器""抓取所有內(nèi)容
那么解析鏈接""中的標(biāo)題
那么把內(nèi)容保存到本地
例子:
#data_source: support\scraper.csv
場(chǎng)景: 退出瀏覽器
那么關(guān)閉瀏覽器
步驟定義如下:
const?assert?=?require('assert');const?{?Util?}?=?require('leanpro.common');
var?{?Given,?When,?Then?}?=?require('cucumber');
const?{?driver?}?=?require('../support/web_driver');
const?{?By,?until?}?=?require("selenium-webdriver");
const?fs?=?require("fs");
const?path?=?require("path");
When("正在抓取{string}網(wǎng)站",?async?function?(site)?{
????//?顯示在報(bào)告中
});
Then("搜索關(guān)鍵詞{string}由{string}",?async?function?(keyword,?search_url)?{
????//?使用關(guān)鍵詞替換鏈接中的%s
????let?url?=?search_url.replace('%s',?keyword);
????await?driver.get(url);
});
Then("使用選擇器{string}抓取所有內(nèi)容",?async?function?(selector)?{
????await?driver.wait(until.elementsLocated({?css:?selector?}),?5000,?"超出等待時(shí)間");
????this.blockList?=?await?driver.findElements({css:?selector});
});
Then("解析鏈接{string}中的標(biāo)題",?async?function?(selector)?{
????let?itemListPromise?=?this.blockList.map(async(block)?=>?{
????????let?title?=?await?block.findElement({?css:?selector?}).getText();
????????let?url?=?await?block.findElement({?css:?selector?}).getAttribute("href");
????????return?{title,?url};
????})
????let?itemList?=?await?Promise.all(itemListPromise);
????this.attach(JSON.stringify(itemList,?null,?'\t'));
????this.itemList?=?itemList;
????this.attach(JSON.stringify(itemList,?null,?'\t'));
});
Then("把內(nèi)容保存到本地",?async?function?()?{
????let?filePath?=?path.resolve(__dirname,?'..\\support\\data.csv');
????if(!fs.existsSync(filePath)){
????????fs.writeFileSync(filePath,?'',?{encoding:"utf-8"});
????}
????let?existedData?=?await?Util.loadCsvFile(filePath);
????let?jointData?=?existedData.concat(this.itemList);
????Util.saveToCsvFile(jointData,?filePath);
});
在抓取結(jié)束后,將抓取到的內(nèi)容保存到本地的表格文件中以供其它用途,運(yùn)行結(jié)果生成的data.csv文件內(nèi)容如下:
爬取結(jié)果這個(gè)爬蟲(chóng)中所有的搜索結(jié)果都是簡(jiǎn)單的寫(xiě)入到已有的表格中之后,沒(méi)有進(jìn)行去重的操作,感興趣的讀者同樣可以下載源碼完善這一功能。
總結(jié)
那么以上就是鏈接示例表這一新功能在不同場(chǎng)合的應(yīng)用實(shí)例,除了以上兩種代表性的場(chǎng)合,API 測(cè)試也是它適合的領(lǐng)域,當(dāng)然這個(gè)項(xiàng)目可以直接從 CukeTest 中的樣例api_service來(lái)創(chuàng)建一個(gè) API 測(cè)試項(xiàng)目來(lái)學(xué)習(xí)。回到開(kāi)頭提到的,作為對(duì)Cucumber.js的增強(qiáng),鏈接示例表的新功能大大強(qiáng)化了 CukeTest 完成這種數(shù)據(jù)驅(qū)動(dòng)的測(cè)試的能力,讓您的自動(dòng)化測(cè)試更得心應(yīng)手。
推薦閱讀
1. 教你搭建自己的內(nèi)容聚合網(wǎng)站
總結(jié)
以上是生活随笔為你收集整理的飞书上点链接怎么指定跳转浏览器_链接示例表功能还可以这样用??的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: .pyc文件_python专题shuti
- 下一篇: 用什么来代替switch_一根转动的圆筒