Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spark 如何使用累加器Accumulator

Spark 如何使用累加器Accumulator

作者头像
smartsi
发布于 2019-08-07 06:09:29
发布于 2019-08-07 06:09:29
2.9K00
代码可运行
举报
文章被收录于专栏:SmartSiSmartSi
运行总次数:0
代码可运行

Accumulator 是 spark 提供的累加器,累加器可以用来实现计数器(如在 MapReduce 中)或者求和。Spark 本身支持数字类型的累加器,程序员可以添加对新类型的支持。

1. 内置累加器

在 Spark2.0.0 版本之前,我们可以通过调用 SparkContext.intAccumulator()SparkContext.doubleAccumulator() 来创建一个 Int 或 Double 类型的累加器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Accumulator<Double> doubleAccumulator = sparkContext.doubleAccumulator(0.0, "Double Accumulator");
Accumulator<Integer> intAccumulator = sparkContext.intAccumulator(0, "Int Accumulator");
Accumulator<Double> doubleAccumulator2 = sparkContext.accumulator(0.0, "Double Accumulator 2");
Accumulator<Integer> intAccumulator2 = sparkContext.accumulator(0, "Int Accumulator 2");java

在 Spark2.0.0 之后的版本中,之前的的 Accumulator 已被废除,用 AccumulatorV2 代替:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@deprecated("use AccumulatorV2", "2.0.0")
class Accumulator[T] private[spark] (
    // SI-8813: This must explicitly be a private val, or else scala 2.11 doesn't compile
    @transient private val initialValue: T,
    param: AccumulatorParam[T],
    name: Option[String] = None,
    countFailedValues: Boolean = false)
  extends Accumulable[T, T](initialValue, param, name, countFailedValues)

// Int
@deprecated("use sc().longAccumulator(String)", "2.0.0")
def intAccumulator(initialValue: Int, name: String): Accumulator[java.lang.Integer] =
  sc.accumulator(initialValue, name)(IntAccumulatorParam)
    .asInstanceOf[Accumulator[java.lang.Integer]]

@deprecated("use sc().longAccumulator(String)", "2.0.0")
def accumulator(initialValue: Int, name: String): Accumulator[java.lang.Integer] =
  intAccumulator(initialValue, name)

// Double
@deprecated("use sc().doubleAccumulator(String)", "2.0.0")
def doubleAccumulator(initialValue: Double, name: String): Accumulator[java.lang.Double] =
  sc.accumulator(initialValue, name)(DoubleAccumulatorParam)
    .asInstanceOf[Accumulator[java.lang.Double]]

@deprecated("use sc().doubleAccumulator(String)", "2.0.0")
def accumulator(initialValue: Double, name: String): Accumulator[java.lang.Double] =
  doubleAccumulator(initialValue, name)

我们可以通过调用 sparkContext.sc().longAccumulator()sparkContext.sc().doubleAccumulator() 来创建一个 Long 或 Double 类型的累加器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DoubleAccumulator doubleAccumulator = sparkContext.sc().doubleAccumulator("Double Accumulator");
LongAccumulator longAccumulator = sparkContext.sc().longAccumulator("Long Accumulator");

看一下这两个方法具体的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Create and register a long accumulator, which starts with 0 and accumulates inputs by `add`.
 */
def longAccumulator: LongAccumulator = {
  val acc = new LongAccumulator
  register(acc)
  acc
}

/**
 * Create and register a double accumulator, which starts with 0 and accumulates inputs by `add`.
 */
def doubleAccumulator: DoubleAccumulator = {
  val acc = new DoubleAccumulator
  register(acc)
  acc
}

通过源码我们知道分别通过创建 LongAccumulatorDoubleAccumulator 对象,然后进行注册来创建一个累加器。所以我们也可以使用如下方式创建一个Long类型的累加器:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
LongAccumulator longAccumulator = new LongAccumulator();
sparkContext.sc().register(longAccumulator, "Long Accumulator");

LongAccumulator DoubleAccumulator 都继承自 AccumulatorV2

Spark内置了数值型累加器(例如,Long,Double类型),我们还可以通过继承 AccumulatorV2 来创建我们自己类型的累加器。

2. 自定义累加器

自定义累加器类型的功能在 1.x 版本中就已经提供了,但是使用起来比较麻烦,在 Spark 2.0.0 版本后,累加器的易用性有了较大的改进,而且官方还提供了一个新的抽象类:AccumulatorV2 来提供更加友好的自定义类型累加器的实现方式。官方同时给出了一个实现的示例:CollectionAccumulator,这个类允许以集合的形式收集 Spark 应用执行过程中的一些信息。例如,我们可以用这个类收集 Spark 处理数据过程中的非法数据或者引起异常的异常数据,这对我们处理异常时很有帮助。当然,由于累加器的值最终要汇聚到 Driver 端,为了避免 Driver 端的出现 OOM,需要收集的数据规模不宜过大。

实现自定义类型累加器需要继承 AccumulatorV2 并覆盖下面几个方法:

  • reset 将累加器重置为零
  • add 将另一个值添加到累加器中
  • merge 将另一个相同类型的累加器合并到该累加器中。

下面这个累加器可以用于在程序运行过程中收集一些异常或者非法数据,最终以 List[String] 的形式返回:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.sjf.open.spark;

import com.google.common.collect.Lists;
import org.apache.spark.util.AccumulatorV2;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义累加器 CollectionAccumulator
 * @author sjf0115
 * @Date Created in 下午2:11 18-6-4
 */
public class CollectionAccumulator<T> extends AccumulatorV2<T, List<T>> {

    private List<T> list = Lists.newArrayList();

    @Override
    public boolean isZero() {
        return list.isEmpty();
    }

    @Override
    public AccumulatorV2<T, List<T>> copy() {
        CollectionAccumulator<T> accumulator = new CollectionAccumulator<>();
        synchronized (accumulator) {
            accumulator.list.addAll(list);
        }
        return accumulator;
    }

    @Override
    public void reset() {
        list.clear();
    }

    @Override
    public void add(T v) {
        list.add(v);
    }

    @Override
    public void merge(AccumulatorV2<T, List<T>> other) {
        if(other instanceof CollectionAccumulator){
            list.addAll(((CollectionAccumulator) other).list);
        }
        else {
            throw new UnsupportedOperationException("Cannot merge " + this.getClass().getName() + " with " + other.getClass().getName());
        }
    }

    @Override
    public List<T> value() {
        return new ArrayList<>(list);
    }
}

下面我们在数据处理过程中收集非法坐标为例,来看一下我们自定义的累加器如何使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.sjf.open.spark;

import com.google.common.collect.Lists;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;

import java.io.Serializable;
import java.util.List;

/**
 * 自定义累加器示例
 * @author sjf0115
 * @Date Created in 下午2:11 18-6-4
 */
public class CustomAccumulatorExample implements Serializable{

    public static void main(String[] args) {
        String appName = "CustomAccumulatorExample";
        SparkConf conf = new SparkConf().setAppName(appName);
        JavaSparkContext sparkContext = new JavaSparkContext(conf);

        List<String> list = Lists.newArrayList();
        list.add("27.34832,111.32135");
        list.add("34.88478,185.17841");
        list.add("39.92378,119.50802");
        list.add("94,119.50802");

        CollectionAccumulator<String> collectionAccumulator = new CollectionAccumulator<>();
        sparkContext.sc().register(collectionAccumulator, "Illegal Coordinates");
        // 原始坐标
        JavaRDD<String> sourceRDD = sparkContext.parallelize(list);
        // 过滤非法坐标
        JavaRDD<String> resultRDD = sourceRDD.filter(new Function<String, Boolean>() {
            @Override
            public Boolean call(String str) throws Exception {
                String[] coordinate = str.split(",");
                double lat = Double.parseDouble(coordinate[0]);
                double lon = Double.parseDouble(coordinate[1]);
                if(Math.abs(lat) > 90 || Math.abs(lon) > 180){
                    collectionAccumulator.add(str);
                    return true;
                }
                return false;
            }
        });
        // 输出
        resultRDD.foreach(new VoidFunction<String>() {
            @Override
            public void call(String coordinate) throws Exception {
                System.out.println("[Data]" + coordinate);
            }
        });
        // 查看异常坐标
        for (String coordinate : collectionAccumulator.value()) {
            System.out.println("[Illegal]: " + coordinate);
        }
    }

}

结果输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Illegal]: 94,119.50802
[Illegal]: 34.88478,185.17841

3. 累加器注意事项

累加器不会改变 Spark 的懒加载(Lazy)的执行模型。如果在 RDD 上的某个操作中更新累加器,那么其值只会在 RDD 执行 action 计算时被更新一次。因此,在 transformation (例如, map())中更新累加器时,其值并不能保证一定被更新。

Spark 中的一系列 transformation 操作会构成一个任务链,需要通过 action 操作来触发。累加器也是一样的,也只能通过 action 触发更新,所以在 action 操作之前调用 value 方法查看其数值是没有任何变化的。对于在 action 中更新的累加器,Spark 会保证每个任务对累加器只更新一次,即使重新启动的任务也不会重新更新该值。而如果在 transformation 中更新的累加器,如果任务或作业 stage 被重新执行,那么其对累加器的更新可能会执行多次。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.sjf.open.spark;

import com.google.common.collect.Lists;
import org.apache.spark.Accumulator;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.util.CollectionAccumulator;
import org.apache.spark.util.DoubleAccumulator;
import org.apache.spark.util.LongAccumulator;

import java.io.Serializable;
import java.util.List;

/**
 * 累加器陷阱
 * @author sjf0115
 * @Date Created in 下午2:11 18-6-4
 */
public class AccumulatorTrap implements Serializable{

    public static void main(String[] args) {
        String appName = "AccumulatorTrap";
        SparkConf conf = new SparkConf().setAppName(appName);
        JavaSparkContext sparkContext = new JavaSparkContext(conf);

        LongAccumulator evenAccumulator = sparkContext.sc().longAccumulator("Even Num Accumulator");
        LongAccumulator oddAccumulator = sparkContext.sc().longAccumulator("Odd Num Accumulator");

        /*LongAccumulator evenAccumulator = new LongAccumulator();
        LongAccumulator oddAccumulator = new LongAccumulator();

        sparkContext.sc().register(evenAccumulator, "Even Num Accumulator");
        sparkContext.sc().register(oddAccumulator, "Odd Num Accumulator");*/

        List<Integer> numList = Lists.newArrayList();
        for(int i = 0;i < 10;i++){
            numList.add(i);
        }
        JavaRDD<Integer> numRDD = sparkContext.parallelize(numList);

        // transform
        JavaRDD<Integer> resultRDD = numRDD.map(new Function<Integer, Integer>() {
            @Override
            public Integer call(Integer num) throws Exception {
                if (num % 2 == 0) {
                    evenAccumulator.add(1L);
                    return 0;
                } else {
                    oddAccumulator.add(1L);
                    return 1;
                }
            }
        });

        // the first action
        resultRDD.count();
        System.out.println("Odd Num Count : " + oddAccumulator.value());
        System.out.println("Even Num Count : " + evenAccumulator.value());

        // the second action
        resultRDD.foreach(new VoidFunction<Integer>() {
            @Override
            public void call(Integer num) throws Exception {
                System.out.println(num);
            }
        });
        System.out.println("Odd Num Count : " + oddAccumulator.value());
        System.out.println("Even Num Count : " + evenAccumulator.value());
    }
}

在第一个 action 算子 count 执行之后,累加器输出符合我们预期的结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Odd Num Count : 5
Even Num Count : 5

在第二个 action 算子 foreach 执行之后,累加器输出结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Odd Num Count : 10
Even Num Count : 10

其实这个时候又执行了一次 map 操作,所以累加器各自又增加了5,最终获得的结果变成了10。

看了上面的分析以及输出结果,我们知道,那就是使用累加器的过程中只能使用一次 action 操作才能保证结果的准确性。事实上,这种情况是可以解决的,只要将任务之间的依赖关系切断就可以。我们可以调用 cache,persist 等方法将之前的依赖切断,后续的累加器就不会受之前的 transfrom 操作影响了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Odd Num Count : 5
Even Num Count : 5
Odd Num Count : 5
Even Num Count : 5

所以在使用累加器时,为了保证准确性,最好只使用一次 action 操作。如果需要使用多次,可以使用 cache 或 persist 操作切断依赖。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-06-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
趣解开闭原则之《我发誓!再也不买一体机了》
小王大学毕业后,找了一份像样的工作,早八晚五轻松自在,并且收入也不错。自从大学毕业后,家里用的电脑还是他上大学的时候用了四年的电脑,配置性能早已跟不上现在的时代了。他决定用自己赚的工资买一台家用电脑。
爪哇缪斯
2023/09/01
1910
趣解开闭原则之《我发誓!再也不买一体机了》
设计模式六大原则(五)----迪米特法则
迪米特法则(Law of Demeter )又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能少的了解。不和陌生人说话。英文简写为: LoD。
用户7798898
2021/06/17
8.1K1
如何破解一台智能咖啡机
随着物理网的普及,其安全性尤其重要,近日有国外黑客破解一台智能咖啡机,下面就一起来看一下吧。 故事起因 最近一名意大利黑客Simone Margaritelli破解了一台智能咖啡机,Simone是一名移动安全研究员,同时从事高级汇编、C、C++语言开发软件工作,并在Zimperium公司任职,曾开发一款软件工具bettercap,利用这款工具可完成中间人攻击测试。平时Simone很喜欢喝咖啡,于是在几天前他购买了一款咖啡机,并可通过APP来控制咖啡机。于是他就尝试利用逆向工程来控制咖啡机,并达成自己的目的。
FB客服
2018/02/09
8960
如何破解一台智能咖啡机
穿越十年后看互联网+:家电行业的金矿在哪里?
现在市场上炒得火热的智能家居未来出路在何方?做智能家居的创业者应该注意哪些机会?传统家电厂商又到底如何借助互联网进行转型?本文以智能空调为例,用故事的形式,提前带你进入激动人心的未来世界。
IT阅读排行榜
2018/08/13
4980
Service 应该定义怎样的方法?
最近在代码审查时,会发现一些校招新同学会把一些步骤当做 Service 的方法,在 Facade 层对这些步骤进行编排来完成一个完整的功能。这显然是不太正常的。
明明如月学长
2022/01/25
3941
Service 应该定义怎样的方法?
趣解设计模式之《为什么租房子要找中介?》
小王大学毕业了,打算来北京闯荡一下,于是就先寄宿到了他的表姐家,白天的时候,自己在外面小区转一转,看看能不能找到可以租到的房子,他找了好几天都没有找到合适的,要么就是小区里一张租房子的广告都没有,好不容易找到几个,里面的房间大小和价格又不合适。北京实在是太大了,而且这边人生地不熟的,找房子真的是耗费了他大量的力气。
爪哇缪斯
2023/10/06
1780
趣解设计模式之《为什么租房子要找中介?》
面试官:设计原则有哪些?什么是里式替换原则?
RBAC:基于角色的访问控制(Role-Based Access Control)
爪哇缪斯
2023/05/10
2470
面试官:设计原则有哪些?什么是里式替换原则?
给大家简简单单介绍一下设计模式
👨‍🎓作者:Java学术趴 🏦仓库:Github、Gitee ✏️博客:CSDN、掘金、InfoQ、云+社区 🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。 🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。 ☠️每日毒鸡汤:这个社会是存在不公平的,不要抱怨,因为没有用!人总是在反省中进步的! 👋大家好!我是你们的老朋友Java学术趴,又到了一年一度最佳找工作的时节,你拿到心仪的offer了吗?基于大多数粉丝的要求,让小编写整理一些面
Java学术趴
2022/05/19
3580
给大家简简单单介绍一下设计模式
LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关
prompt(提示词)是我们和 LLM 互动最常用的方式,我们提供给 LLM 的 Prompt 作为模型的输入,并希望 LLM 反馈我们期待的结果。 虽然 LLM 的功能非常强大,但 LLM 对提示词(prompt)也非常敏感。这使得提示词工程成为一项需要培养的重要技能。
汀丶人工智能
2024/05/09
3.8K0
LLM 大模型学习必知必会系列(二):提示词工程-Prompt Engineering 以及实战闯关
学会这10个设计原则,离架构师又进了一步!!!
一个懂设计原则的程序猿,写出来的代码可扩展性就是强,后续的人看代码如沐春风。相反,如果代码写的跟流水账似的,完全一根筋平铺下来,后续无论换谁接手维护都要骂娘。
麦洛
2021/07/05
2990
学会这10个设计原则,离架构师又进了一步!!!
大数据运维三十六计
随着互联网的发展,大数据正在以惊人的速度被创造和收集着,尤其随着诸如Google和Alibaba等互联网公司的崛起,数据的价值越来越得到认可,甚至被公司定义为战略资源。因此越来越多的公司开始搭建自己的大数据平台,用来处理数据,从中挖掘商业价值。大数据运维正是在这样的背景下发展起来的,它与传统领域的运维有很多共性的地方,也有一些自身的特点。 第一个特点是规模大 大数据领域单个集群的规模一般是几百台物理机,多则上万台。为了满足容灾需求,一般会有多个集群,而且是跨地域部署的。集群规模大
用户1682855
2018/06/08
2.7K0
面向程序员的数据挖掘指南(一)
作者:Ron Zacharski 第一章:简介 内容: 寻找事物 本书结构 阅读完本书后你可以做些什么? 为什么数据挖掘很重要?哪些内容可以为我所用? 标题里的“Numerati的古老艺术”是什么意思
小莹莹
2018/04/24
7480
面向程序员的数据挖掘指南(一)
如何成为Android高手 博客分类: 经典文章转载 Android互联网中国移动网络应用应用服务器
若立志成为Android高手 ,如有耐心,“一瓶一钵足矣”。   “天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。”想成为Android高手?这可不是想象中写几行 代码 那么容易的事情,但也不是不可实现。   如何做?   1,学会懒惰!奇怪吧?但是,你一定也听说过和感受过这个世界某种程度上是由懒人推动的,生命在于懒惰,懒人创造世界。当然,懒惰也是真的傻傻的呆在 那里什么都不做,而是说要善于想出做事情的更好的方式,这样就可以节约大量的时间,也就有更多的机会懒惰了,同事也懒出了境界。在Android中如何懒 惰?《如何成为Android高手》一文就如何在Android中学会懒惰和朋友们进行了分享。   2,精通Android体系架构、MVC、常见的 设计 模式、控制反转(IoC):这一点难吗?“学之,则难者亦易矣;不学,则易者亦难矣。”   3,编写可重用、可扩展、可维护、灵活性高的代码:Android 应用 程序 开发 的使用纯粹面向对象的Java 作为开发语言,自然也就继承了关于Java关于面向对象的优秀想思想,如何做?《如何成为Android高手》一文就如何在Android中编写可重用、可扩展、可维护、灵活性高的代码和朋友们进行了分享。   4,高效的编写高效的代码:高效的编写代码和编写高效的代码好像天生就是死敌。似乎开发速度上去了,程序的执行效率就下去了;程序的执行效率上去,开发速度就下去了。如何 解决 二者的忙着,请听《如何成为Android高手》一文想大家娓娓道来。   5,学会至少一门服务器端开发技术:没搞错吧,成为Android高手还需要 学习 服务端开发技术?对,需要!《如何成为Android高手》一文就该问题和大家进行了分享。   “蜀之鄙,有二僧:其一贫,其一富。贫者语于富者曰:"吾欲之南海,何如?"富者曰:"子何恃而往?"曰:"吾一瓶一钵足矣。"富者曰:"吾数年来欲 买舟而下,犹未能也。子何恃而往!"越明年,贫者自南海还,以告富者,富者有惭色。西蜀之去南海,不知几千里也,僧富者不能至,而贫者至之,人之立志,顾 不如蜀鄙之僧哉 ”   若立志成为Android高手,如有耐心,“一瓶一钵足矣”。 Android一出生就被打上了富二代的胎记,不仅仅是因为诞生于当今的 网络 霸主Google ,更主要还有一个空前强大和壮观的开放手机 联盟OHA(Open Handset Alliance)提供全力的支持。OHA是什么?OHA涵盖了中国移动、T-Mobile、Sprint等移动运营商,包括HTC 、Motolora、三星等手机制造商,有Google为代表的手机软件 商,还有Inter、Nvidia为标志的底层硬件厂商和Astonishing Tribe等商业运作公司,该组织声称组织的所有成员都会基于Android来开发新的手机业务。   但是,要成为Android高手并不是一件容易的事情。并不是很多人想象的能够飞快的写出几行漂亮的代码去解决一些困难的问题就是Android高手了。真正的Android高手需要考虑的问题远远不是写些漂亮的代码就足够的。
chroya
2018/10/31
5650
精读《可维护性思考》
前端精读之前写了 23 篇设计模式总结文,再加上 6 种设计原则,开闭、单一职责、依赖倒置、接口分离、迪米特法则、里氏替换原则,基本上对代码的可维护性有了全面深刻的理解。
黄子毅
2022/03/15
2980
精读《可维护性思考》
📑教你如何编写一份 API 文档
当你购买一件新产品时,它会附带一本说明书,指导你如何使用。你不会希望把新买的游戏机带回家开箱后发现没有一本关于设置、使用和维护的手册。如果客户不知道如何使用产品,他们就不太可能被公司的产品吸引或在未来购买其他产品。
oil欧呦
2024/05/07
2940
从“挖光缆”到“剪网线”|蚂蚁金服异地多活的微服务体系
本文介绍了蚂蚁金服异地多活单元化架构的原理,以及微服务体系在此架构下的关键技术实现。
数据和云
2018/12/19
1.3K0
从“挖光缆”到“剪网线”|蚂蚁金服异地多活的微服务体系
全栈软件测试工程师宝典连载(4)
现在软件测试界对软件自动化测试非常重视,每年有各种各样的软件测试大会,而这些大会的关注点都集中在软件自动化测试,对软件测试自动化开始重视了,这是一件好事情,本书下篇也都是介绍软件测试自动化的。但是另一方面,据权威报告,2019年在中国仅有5%的软件公司做到了完全意义上的软件自动化测试,这说明了什么?请读者自己思考一下。读者都知道软件开发,不管采取什么样的开发模型,都离不开分析、设计、编码、测试和部署5个环节,而软件测试也可以分为测试分析、测试设计、测试准备(包括测试数据的准备、测试代码的开发、测试环境的搭建等几个方面)、测试执行和测试总结。而现在AI技术刚刚起步,虽然一些大厂开始尝试用AI技术来进行软件测试分析、设计与执行,但是效果并不理想,MBT(Model Base Test:基于模型的软件测试)落地也非常困难,自动化软件测试也仅仅在软件测试执行方面起到了非常重要的作用,虽然随着DevOps概念的提出,软件测试的左移和右移也被提出,但是发现缺陷仍旧是软件测试的关键目标,而大部分缺陷还是需要靠人工测试来完成,软件自动化测试主要作用也仅仅在回归测试起到关键的作用。一方面在开发自动化软件测试代码之前,肯定也进行手工测试,否则自动化测试中的断言是无法获知的;另一方面自动化软件测试对被测程序也要进行分析和设计,所以软件测试分析与设计是软件测试的灵魂,是一个不可被忽略的要素。
顾翔
2021/01/18
3750
腾讯云TVP史海峰:从烽火台到物联网
10月19日,云+社区开发者大会(北京站)圆满落幕。本次开发者大会的主题为“5G探索:核心技术与挑战”,邀请了腾讯内部及业内行业大咖就5G场景下应该如何面对新业务与挑战?大型网站的技术应该如何进化?如何真正理解万物互联?5G有哪些值得探索与实践的方向?5G对应用发展的影响有哪些?等问题进行了深度探讨。同时,在圆桌论坛环节,各位技术专家也与到场的开发者们展开了开放式对话,精彩不断。下边是史海峰老师关于5G时代是否能实现万物互联的分享。
TVP官方团队
2019/11/07
2.6K1
腾讯云TVP史海峰:从烽火台到物联网
像素时代的黄昏和“淘宝叛军”
浅友们好~我是史中,我的日常生活是开撩五湖四海的科技大牛,我会尝试各种姿势,把他们的无边脑洞和温情故事讲给你听。
浅黑科技
2022/06/06
5130
像素时代的黄昏和“淘宝叛军”
从烽火台到物联网
虽然我们还不能完全掌握生命的机理,但基于对基因的理解,我们知道一切生命体的核心都在于信息,是信息载体,也是信息处理器。
IT民工闲话
2019/11/14
1.2K1
从烽火台到物联网
推荐阅读
相关推荐
趣解开闭原则之《我发誓!再也不买一体机了》
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验