Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
用流程
1. 定義測(cè)試用例
2. 驗(yàn)證測(cè)試用例
以示例接口 新聞列表為例,新聞列表返回響應(yīng)數(shù)據(jù)如下:
```javascript
{
"code": 10000,
"msg": "success",
"data": {
"cur_page": "1",
"last_page": 2,
"page_size": "20",
"total": 30,
"list": [
{
"id": 3,
"title": "前后僅用了4分鐘,16枚洲際導(dǎo)彈應(yīng)聲而出,美航母也不敢輕舉妄動(dòng)",
"author": "烽火雜志",
"url": "https://open.apipost.cn/",
"content": "世界上哪個(gè)國(guó)家可與美軍抗衡?國(guó)際社會(huì)上關(guān)于這一問題的答案千奇百怪,但有一個(gè)國(guó)家用行動(dòng)讓美軍閉嘴,短短4分鐘連續(xù)發(fā)射16枚洲際導(dǎo)彈,場(chǎng)面十分壯觀,讓西方國(guó)家畏懼不已,即便是美航母也不敢輕舉妄動(dòng)。"
}
]
}
}
```
定義入口在后執(zhí)行腳本里;
特別注意:==每個(gè)測(cè)試用例是一行,不能換行。==
通用和常用的測(cè)試用例定義如下:
```javascript
apt.assert('response.raw.responseText=="test"');
apt.assert('response.raw.status==200');
apt.assert('response.raw.type=="json"');
apt.assert('response.raw.responseTime>=100');
apt.assert('response.json.errcode==1');
apt.assert('response.json.errcode!=1');
apt.assert('response.json.errcode>=1');
apt.assert('response.json.errcode==null');
apt.assert('response.json.errcode!=null');
apt.assert('response.headers["server"]=="nginx"');
apt.assert('response.headers["content-encoding"]=="gzip"');
apt.globals.set("key", "value");
apt.globals.get("key");
apt.globals.delete("key");
apt.globals.clear();
apt.variables.set("key", "value");
apt.variables.get("key");
apt.variables.delete("key");
apt.variables.clear();
$.ajax({
"url":"https://echo.apipost.cn/token.php",
"method":"POST",
"async":false,
"content-type":"appicateion-json",
"data":JSON.stringify({
"email":"admin@admin.com",
"password":"密碼"
}),
"success":function(response){
response=typeof response=="object" ? response : JSON.parse(response);
console.log(response);
apt.variables.set("token", response.token);
}
});
```
針對(duì)新聞列表這個(gè)接口測(cè)試用例定義如下:
```javascript
apt.assert('response.raw.status==200');
apt.assert('response.raw.type=="json"');
apt.assert('response.raw.responseTime>=100');
apt.assert('response.json.code==10000');
apt.assert('response.json.msg=="success"');
apt.assert('response.raw.responseText.indexOf("data") > -1'); // 檢查響應(yīng)文本是否含有data字符串
apt.assert('response.json.hasOwnProperty("data")'); // 檢測(cè)返回json對(duì)象的是否含有data字段
apt.assert('response.json.data.cur_page=="1"');
apt.assert('response.json.data.last_page==2');
apt.assert('response.json.data.page_size=="20"');
apt.assert('response.json.data.total==30');
```
下圖為運(yùn)行效果圖
綠色表示測(cè)試通過,紅色表示測(cè)試不通過
再加一個(gè)明顯不通過的定義:apt.assert('response.raw.responseText=="test"');
```javascript
apt.assert('response.raw.responseText=="test"');
apt.assert('response.raw.status==200');
apt.assert('response.raw.type=="json"');
apt.assert('response.raw.responseTime>=100');
apt.assert('response.json.code==10000');
apt.assert('response.json.msg=="success"');
apt.assert('response.raw.responseText.indexOf("data") > -1'); // 檢查響應(yīng)文本是否含有data字符串
apt.assert('response.json.hasOwnProperty("data")'); // 檢測(cè)返回json對(duì)象的是否含有data字段
apt.assert('response.json.data.cur_page=="1"');
apt.assert('response.json.data.last_page==2');
apt.assert('response.json.data.page_size=="20"');
apt.assert('response.json.data.total==30');
```
結(jié)果如圖:
定義如下:
```javascript
//驗(yàn)證集合list測(cè)試用例定義;
// 筆者暫時(shí)還沒有找到添加斷言業(yè)務(wù)描述的參數(shù)方法,一般斷言有斷言描述和斷言表達(dá)式。但這個(gè)語法上好像不支持。
// 后期如果找到一并補(bǔ)充上
if(response.json.hasOwnProperty("data")){
// apt.assert('response.raw.responseText=="test"');
if(response.json.data.hasOwnProperty("list")
&& response.json.data.list.length>0){
// apt.assert('response.raw.responseText=="test"');
for(var i=0;i<response.json.data.list.length;i++){
apt.assert(true,"i="+i);
var item=response.json.data.list[i];
response.json.data.item=item;
apt.assert('response.json.data.item.hasOwnProperty("id")');
apt.assert('response.json.data.item.hasOwnProperty("title")');
apt.assert('response.json.data.item.hasOwnProperty("author")');
apt.assert('response.json.data.item.hasOwnProperty("url")');
apt.assert('response.json.data.item.hasOwnProperty("content")');
}
}
}
```
結(jié)果見下圖:
筆者暫時(shí)還沒有找到添加斷言業(yè)務(wù)描述的參數(shù)方法,一般斷言有斷言描述和斷言表達(dá)式。但這個(gè)語法上好像不支持。后期如果找到一并補(bǔ)充上
示例接口由于是動(dòng)態(tài)環(huán)境,所以數(shù)據(jù)值會(huì)發(fā)生變化,不利于進(jìn)行原始數(shù)據(jù)與后期接口獲取的數(shù)據(jù)進(jìn)行數(shù)據(jù)文件上的驗(yàn)證。
如不理解沒有關(guān)系,這個(gè)屬于業(yè)務(wù)數(shù)據(jù)驅(qū)動(dòng)接口測(cè)試的一種測(cè)試?yán)砟睢R话阍诖笮颓腋鞣N資源比較充沛的團(tuán)隊(duì)才進(jìn)行這樣的從服務(wù)環(huán)境、數(shù)據(jù)庫、業(yè)務(wù)數(shù)據(jù)添加,修改,刪除等一系列流程上完全被定義可預(yù)測(cè)且能驗(yàn)證的整體可測(cè)的測(cè)試設(shè)計(jì)。
不過筆者搞開發(fā)十多年也沒有見過這樣的大手筆。可能大廠有吧!一般幾十剛過百人的研發(fā)團(tuán)隊(duì)就算了。沒那必要性。
不過如果是支撐大流量且需要在高速奔跑火車上換換輪子的極端情況,搞這么一個(gè)十個(gè)人左右的小的數(shù)據(jù)驅(qū)動(dòng)一切可測(cè)設(shè)計(jì)的測(cè)試團(tuán)隊(duì)還是有比較可觀的收益的。這樣可評(píng)估線上生產(chǎn)環(huán)境的風(fēng)險(xiǎn)范圍以及當(dāng)前研發(fā)團(tuán)隊(duì)的研發(fā)質(zhì)量和風(fēng)險(xiǎn)意識(shí)。
期待擴(kuò)展出使用json等格式文件進(jìn)行數(shù)據(jù)斷言的版本
搞開發(fā)這些年見過很多給開發(fā)打績(jī)效的方案:
比如:按代碼量的,按工時(shí)的,按編碼時(shí)長(zhǎng)的,按提交數(shù)量的等等方式。只能說有比沒有好吧!在表面搞搞人力績(jī)效還是很能讓老板滿意的,于是各種加班996,007就出現(xiàn)了。
其實(shí)開發(fā)質(zhì)量是可以從API接口測(cè)試?yán)矬w現(xiàn)出來的能兼容的場(chǎng)景參數(shù)越多,服務(wù)越穩(wěn)定。技術(shù)當(dāng)然會(huì)比較好。當(dāng)然筆者的觀點(diǎn)估計(jì)不好理解和接受。這種用單元測(cè)試來衡量開發(fā)質(zhì)量的還得是開發(fā)自己人來搞。不過接口工具的出現(xiàn)到提供了非開發(fā)人員來量化開發(fā)人員質(zhì)量,也許是不錯(cuò)的方式。
言
處理網(wǎng)頁數(shù)據(jù)時(shí),我們經(jīng)常需要從HTML中提取日期信息。日期格式多樣,從HTML文檔中準(zhǔn)確地提取并驗(yàn)證這些信息是一項(xiàng)挑戰(zhàn)。本文將詳細(xì)介紹如何使用正則表達(dá)式從HTML中提取日期,并用Python代碼進(jìn)行有效性驗(yàn)證。
一、正則表達(dá)式基礎(chǔ)
概念:
正則表達(dá)式是用于文本搜索和替換的強(qiáng)大工具,它能夠描述復(fù)雜的模式。
基本語法元素:
字符集:[0-9]匹配任意數(shù)字,[a-zA-Z]匹配任意字母。
量詞:*(零次或多次)、+(一次或多次)等。
特殊字符:.匹配任意單個(gè)字符,\d匹配任意數(shù)字。
分組:(19|20)\d\d匹配以19或20開頭的年份。
二、從HTML中提取日期
HTML結(jié)構(gòu)分析:
檢查網(wǎng)頁源代碼,找到包含日期的標(biāo)簽或?qū)傩浴?/p>
日期可能以不同格式存在,比如文本形式或?qū)傩灾怠?/p>
構(gòu)建正則表達(dá)式:
針對(duì)YYYY-MM-DD、DD-MM-YYYY、MM/DD/YYYY等格式編寫正則表達(dá)式。
考慮HTML文檔結(jié)構(gòu)的差異,調(diào)整正則表達(dá)式以提高匹配的準(zhǔn)確性。
三、驗(yàn)證日期的有效性
日期格式驗(yàn)證:
確保提取的字符串符合日期格式,但還需要進(jìn)一步驗(yàn)證日期的實(shí)際有效性。
正則表達(dá)式初步驗(yàn)證:
使用正則表達(dá)式確保日期組件在合理范圍內(nèi),如月份應(yīng)在01至12之間。
編程驗(yàn)證日期有效性:
使用Python的datetime模塊進(jìn)行進(jìn)一步驗(yàn)證。
考慮特殊情況,如閏年和每月的實(shí)際天數(shù)。
四、實(shí)際案例分析
案例演示:
選取具有代表性的網(wǎng)頁HTML樣本,標(biāo)識(shí)其中的日期信息。
編寫適用的正則表達(dá)式來匹配這些日期。
代碼實(shí)現(xiàn):
使用Python演示如何應(yīng)用正則表達(dá)式提取日期。
展示如何使用datetime模塊驗(yàn)證日期有效性。
五、總結(jié)與展望
總結(jié):
正則表達(dá)式是提取HTML中日期信息的有效工具,但還需通過編程驗(yàn)證其有效性。
未來應(yīng)用:
探討正則表達(dá)式在數(shù)據(jù)分析、日志處理等領(lǐng)域的應(yīng)用。
小結(jié)
本文提供了一個(gè)全面的指南,說明了如何使用正則表達(dá)式從HTML文檔中提取日期,并通過Python代碼進(jìn)行驗(yàn)證。這些技能對(duì)于數(shù)據(jù)抓取和文本處理領(lǐng)域非常重要。
Python 代碼示例
1. 正則表達(dá)式提取日期
python
import re
from datetime import datetime
# 示例HTML內(nèi)容
html_content="""
<p>發(fā)表日期:2020-12-15</p>
<p>更新日期:2021/01/20</p>
<p>活動(dòng)日期:31-01-2022</p>
"""
# 正則表達(dá)式匹配不同的日期格式
date_patterns=[
r'\d{4}-\d{2}-\d{2}', # YYYY-MM-DD
r'\d{2}/\d{2}/\d{4}', # DD/MM/YYYY
r'\d{2}-\d{2}-\d{4}' # DD-MM-YYYY
]
# 提取日期
extracted_dates=[]
for pattern in date_patterns:
matches=re.findall(pattern, html_content)
extracted_dates.extend(matches)
print("Extracted Dates:", extracted_dates)
2. 驗(yàn)證日期有效性
python
# 驗(yàn)證日期有效性
def validate_date(date_str):
for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%d-%m-%Y"):
try:
datetime.strptime(date_str, fmt)
return True
except ValueError:
continue
return False
# 驗(yàn)證提取的日期
valid_dates=[date for date in extracted_dates if validate_date(date)]
print("Valid Dates:", valid_dates)
在這個(gè)例子中,我們首先使用正則表達(dá)式從HTML內(nèi)容中提取日期,然后使用Python的datetime模塊驗(yàn)證這些日期的有效性。這種方法適用于不同格式的日期,并能有效地識(shí)別和排除無效日期。
validator.js是一個(gè)Github上專門針對(duì)字符串校驗(yàn)所建立的一個(gè)工具庫,validator.js包含了大量實(shí)用的字符串校驗(yàn)和清洗方法,并且支持在Node環(huán)境和瀏覽器環(huán)境使用,非常實(shí)用。
https://github.com/validatorjs/validator.js
包管理方式安裝
npm install validator
//或者
yarn add validator
可以在各種開發(fā)場(chǎng)景下使用
var validator=require('validator');
validator.isEmail('foo@bar.com'); //=> true
可以一次性全部導(dǎo)入
import validator from 'validator';
也可以針對(duì)不同方法單獨(dú)引入,比如我們只需要導(dǎo)入驗(yàn)證郵箱的方法
import isEmail from 'validator/lib/isEmail';
或者Tree-shakeable ES imports導(dǎo)入
import isEmail from 'validator/es/lib/isEmail';
<script type="text/javascript" src="validator.min.js"></script>
<script type="text/javascript">
validator.isEmail('foo@bar.com'); //=> true
</script>
方法非常豐富,可以根據(jù)需要進(jìn)行使用,建議先看一下Github上中每個(gè)方法的含義和使用方式。
import toDate from './lib/toDate';
import toFloat from './lib/toFloat';
import toInt from './lib/toInt';
import toBoolean from './lib/toBoolean';
import equals from './lib/equals';
import contains from './lib/contains';
import matches from './lib/matches';
import isEmail from './lib/isEmail';
import isURL from './lib/isURL';
import isMACAddress from './lib/isMACAddress';
import isIP from './lib/isIP';
import isIPRange from './lib/isIPRange';
import isFQDN from './lib/isFQDN';
import isDate from './lib/isDate';
import isBoolean from './lib/isBoolean';
import isLocale from './lib/isLocale';
import isAlpha, { locales as isAlphaLocales } from './lib/isAlpha';
import isAlphanumeric, { locales as isAlphanumericLocales } from './lib/isAlphanumeric';
import isNumeric from './lib/isNumeric';
import isPassportNumber from './lib/isPassportNumber';
import isPort from './lib/isPort';
import isLowercase from './lib/isLowercase';
import isUppercase from './lib/isUppercase';
import isIMEI from './lib/isIMEI';
import isAscii from './lib/isAscii';
import isFullWidth from './lib/isFullWidth';
import isHalfWidth from './lib/isHalfWidth';
import isVariableWidth from './lib/isVariableWidth';
import isMultibyte from './lib/isMultibyte';
import isSemVer from './lib/isSemVer';
import isSurrogatePair from './lib/isSurrogatePair';
import isInt from './lib/isInt';
import isFloat, { locales as isFloatLocales } from './lib/isFloat';
import isDecimal from './lib/isDecimal';
import isHexadecimal from './lib/isHexadecimal';
import isOctal from './lib/isOctal';
import isDivisibleBy from './lib/isDivisibleBy';
import isHexColor from './lib/isHexColor';
import isRgbColor from './lib/isRgbColor';
import isHSL from './lib/isHSL';
import isISRC from './lib/isISRC';
import isIBAN, { locales as ibanLocales } from './lib/isIBAN';
import isBIC from './lib/isBIC';
import isMD5 from './lib/isMD5';
import isHash from './lib/isHash';
import isJWT from './lib/isJWT';
import isJSON from './lib/isJSON';
import isEmpty from './lib/isEmpty';
import isLength from './lib/isLength';
import isByteLength from './lib/isByteLength';
import isUUID from './lib/isUUID';
import isMongoId from './lib/isMongoId';
import isAfter from './lib/isAfter';
import isBefore from './lib/isBefore';
import isIn from './lib/isIn';
import isCreditCard from './lib/isCreditCard';
import isIdentityCard from './lib/isIdentityCard';
import isEAN from './lib/isEAN';
import isISIN from './lib/isISIN';
import isISBN from './lib/isISBN';
import isISSN from './lib/isISSN';
import isTaxID from './lib/isTaxID';
import isMobilePhone, { locales as isMobilePhoneLocales } from './lib/isMobilePhone';
import isEthereumAddress from './lib/isEthereumAddress';
import isCurrency from './lib/isCurrency';
import isBtcAddress from './lib/isBtcAddress';
import isISO8601 from './lib/isISO8601';
import isRFC3339 from './lib/isRFC3339';
import isISO31661Alpha2 from './lib/isISO31661Alpha2';
import isISO31661Alpha3 from './lib/isISO31661Alpha3';
import isISO4217 from './lib/isISO4217';
import isBase32 from './lib/isBase32';
import isBase58 from './lib/isBase58';
import isBase64 from './lib/isBase64';
import isDataURI from './lib/isDataURI';
import isMagnetURI from './lib/isMagnetURI';
import isMimeType from './lib/isMimeType';
import isLatLong from './lib/isLatLong';
import isPostalCode, { locales as isPostalCodeLocales } from './lib/isPostalCode';
import ltrim from './lib/ltrim';
import rtrim from './lib/rtrim';
import trim from './lib/trim';
import escape from './lib/escape';
import unescape from './lib/unescape';
import stripLow from './lib/stripLow';
import whitelist from './lib/whitelist';
import blacklist from './lib/blacklist';
import isWhitelisted from './lib/isWhitelisted';
import normalizeEmail from './lib/normalizeEmail';
import isSlug from './lib/isSlug';
import isLicensePlate from './lib/isLicensePlate';
import isStrongPassword from './lib/isStrongPassword';
import isVAT from './lib/isVAT';
validator.js是一個(gè)非常值得學(xué)習(xí)的工具庫,不僅是使用它,也可以用它來學(xué)習(xí)一些JavaScript的基礎(chǔ)知識(shí),學(xué)習(xí)其中各類方法的寫法,也可以鞏固JavaScript的基礎(chǔ)知識(shí)!
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。