@yanglfyangl
2018-12-05T04:03:04.000000Z
字数 3582
阅读 645
测试自动化
CI/CD的能力模型中,很重要的一点就是测试自动化的能力,这一点也是很多公司没有做到的能力(有不少大公司都是比0多不了多少)。究其原因,自动化测试的工作量比较是大家很慎重深入它的一个原因。
AI时代,机器学习的发现变化,是不是能有所帮助呢,下面就是碰到一个场景后的一些思考。
大概情况是这样的,朋友问了一个问题,有一大批的数据,这些数据做为输入后,会将最终结果落在数据库中,类似如下场景
数据的格式(虽然贴出来,但其实也看不懂)
<EuronextCode>LU1840350067</EuronextCode>
<IsinCode>LU1840350067</IsinCode>
。。。。。。
。。。。。。
<ExerciseType>2</ExerciseType>
<MarketType>301</MarketType>
<UnderlyingIsinCode>NL0011794037</UnderlyingIsinCode>
<UnderlyingMep>AMS</UnderlyingMep>
<FirstTradingDate>2018-09-21</FirstTradingDate>
<IssueDate>2018-09-21</IssueDate>
<UnderlyingType>301</UnderlyingType>
<StrikePrice>18.675798</StrikePrice>
。。。。。。
。。。。。。
<AuctionTime>00:00:00</AuctionTime>
主要的输出的格式
{
payload:" ",
effective_from:" ",
effective_to:" "
}
当然,主要还有几张表,这个表结构就不多说了。
问题是,在这个场景下,如何快速的进行测试呢?如果考虑边界值,等价类,因果等等的覆盖度,就会陷入下面的情况
1. Case过多
2. 测试时间过长
3. 需求变化对测试影响过大。
能不能用人工智能的方式来简化测试
这个例子是很多测试同学面临的难题,如果按照黑盒测试的方法,有足够的时间,可能还好。但一旦要求快速,就会面临如下难题
1. 量大
2. 中间经过的服务并不是很确定(至少对于测试工程师来说,理解起来不容易)
3. 给的测试时间并不是充分的
4. 逻辑变化导致问题的可能点多,不易发现
当然,自然有人会想到机器学习来“学”出对应的逻辑,再进行测试,不过
1. 不能假设输入与输出一一对应。(逻辑肯定会使用原有的数据库中的值)
2. 数据不是多对一或一对一的,而是多对多的
在机器学习领域,主要分成了
1. 监督学习
2. 非监督学习
当然,背后的各种算法就很多了。
对于这个例子,测试团队估计不太会愿意做“监督”学习,因为样本的建立工作量很大,而且每次逻辑的变化可能都会导致样本重新来做,很划不来的。
这时候,我们能不能换个思路,其实现在的场景中,我们并不是要做预测,而是知道输入和输出的情况下,看输入与输出是不是正确的,这个是不是一个“异常值检测” 的场景呢?
我们先看看使用异常检测的场景
1. 大部分情况下都是正常的
2. 正常的样本数据也大致趋同
3. 小部分情况下是异常的
4. 异常的故障可能多种多样
入参1 | 入参2 | 入参3 | 。。。 | 入参N | 出参1 | 出参2 | 出参N |
---|---|---|---|---|---|---|---|
LU1840350067 | AMS | I am ok | abc | ad | adf | 0.5 | {type:1, value:2} |
... | ... | ... |
这步主要是进行剔除,比如对于ID,可能对我们需要最终的影响从功能上已知是没有多少影响的,就可以从参数列表里去除了。
参数 | 向量化方法 | 描述 |
---|---|---|
入参1 | —————————— | 数据ID,不参与训练 |
入参2 | 将AMS转化对应的枚举值 | |
入参3 | 利用CountVectorizer进行文字向量化 | |
出参N | 将Json拆解出新的参数维度,增加参数N+1。。。 |
这里,每个参数都有可能出现没有的情况,这时候要考虑如何进行补值,按下面思路考虑
如果参数可有可无,补平均值就可以了,目的是不影响最终结果
如果参数很重要,补一个远离平均值的(异常值),这样最终结果也容易发现异常。
如果不知道。。。最好找人弄清楚,要实在弄不清楚,先补0吧。
最终的txt文件会是这样的
200, 111, 0.5, ..., ..., ..., ..., 0.69874
201, 100, 0.8, ..., ..., ..., ..., 0.69874
...
...
...
201, 100, 0.8, ..., ..., ..., ..., 0.51345
上面的过程是把数据准备出来了,下面是看看怎么用这些数据了。
其实,选择什么样的异常值算法,还是要根据你的场景的,但这个例子中,主要的场景其实是给人工测试一个方法,能够快速的发现问题,所以建议采用的是K-Means算法(非监督&聚类),当然,最好是考虑K-Medians或均值漂移聚类,这样不需要考虑质心的问题。
最终可能会出现下面的图。
这时候,测试同学就可以
1. 取样质心中的数据,看看是不是逻辑有问题,如果质心的逻辑数据有问题,那么肯定是重大逻辑错误了。
2. 取样非质心数据,看看是不是有逻辑问题。
自动化测试很核心的点就是不需要人工参与的情况下,自动评估结果是否达到预期,所以聚类的方法还是有些问题的,阈值很难定义。特别是如果算法有问题,多聚类出来一个不应该存在的质心,是不容易进行自动化判断代码是否是符合要求的。
这时候,我们就要找一些能够通过阈值来进行异常值查找的算法了,比如:高斯模型(正态分布)。
这时候,我们呆可以把(μ-σ,μ+σ)范围内的面积做为阈值。
比如,我们认为测试的结果应该有90%符合预期才能进入下一步,就可以进行设定,因为有了“标准”的值,所以自动化就可以跑了。当然,这时候就会产生几个问题
1. 怎么训练模型
2. 怎么计算这个面积
2. 怎么设定这个面积的合理值。
挨个来说
怎么训练模型
说简单也简单,但说复杂,也有一点,需要对所有的输入,进行一个归一化处理,并计算出和来。
mu, sigma , num_bins = 0, 1, 总数
x = mu + sigma * 归一化(x1, x2...xn)
# 正态分布的数据
n, bins, patches = plt.hist(x, num_bins, normed=True, facecolor = 'blue', alpha = 0.5)
//拟合曲线
y = mlab.normpdf(bins, mu, sigma)
怎么计算面积
import math
def pdf(x):
return math.exp(-(x) ** 2 / (2)) / (math.sqrt(2 * math.pi))
def sum_fun_xk(xk, func):
return sum([func(each) for each in xk])
def integral(a, b, n, func):
h = (b - a)/float(n)
xk = [a + i*h for i in range(1, n)]
return h/2 * (func(a) + 2 * sum_fun_xk(xk, func) + func(b))
def cdfd(a,b,u,o):
return integral((a-u)/o,(b-u)/o,10000,pdf)
测试一下
cdfd(2,3,2,1)
Out: 0.3413399854638336
这个问题不容易有一个明确合理的答案。最好的方式可能是先分析一下你的测试,然后找一个认为合适的质量要求度。当然,这个里面最重要的是先用聚类进行第一轮的人工测试,然后新数据与老数据聚类的结果进行第一要素的评判,如果聚类出的核数都有差距,则说明本次有重大功能问题了(或功能有比较大的变化了)
大概的伪代码如下:
var threadhold = 0.05; //简而言之,要求95%的信心
var lastKernNumber = getLastKernNumbers();
var thisKernNumber = getThisKernNumbers();
if(hunmanConfiredNotCheck || lastKernNumber != thisKernNumber) {
throw("自动测试失败,发现与上次有比较大的区别,请重新确认")
}
if(threadhold < getUnNormalArea()){
throw("自动测试失败,测试结果中异常值过多")
}