<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Testing on 翟志军 Jack Zhai</title>
    <link>https://showme.codes/tags/testing/</link>
    <description>Recent content in Testing on 翟志军 Jack Zhai</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <copyright>showme.codes</copyright>
    <lastBuildDate>Sun, 22 Oct 2023 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://showme.codes/tags/testing/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Shell Bash能力对于运维很重要吗？</title>
      <link>https://showme.codes/zh-cn/2023-10-22-shell-bash-non-important/</link>
      <pubDate>Sun, 22 Oct 2023 00:00:00 +0000</pubDate>
      <guid>https://showme.codes/zh-cn/2023-10-22-shell-bash-non-important/</guid>
      <description>不重要是假的，重要也是假的</description>
    </item>
    <item>
      <title>精准测试不过是增量构建的副产品</title>
      <link>https://showme.codes/zh-cn/2023-04-22-accuration-testing-is-wrong-2/</link>
      <pubDate>Sat, 22 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://showme.codes/zh-cn/2023-04-22-accuration-testing-is-wrong-2/</guid>
      <description>&lt;p&gt;前文中，我们给了“精准测试”定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;它是一种能力，能只针对变更进行测试，而不是每次变更都进行全量测试。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;同时，介绍了当前行业里的主流实现方法。个人并不看好该实现方法。&lt;/p&gt;
&lt;p&gt;本文介绍的另一种实现精准测试的方法。在真正介绍前，我们就必须先说增量构建和Bazel。&lt;/p&gt;
&lt;h2 id=&#34;全量构建与增量构建&#34;&gt;全量构建与增量构建&lt;/h2&gt;
&lt;p&gt;在软件构建领域，存在两种构建类型：全量构建和增量构建。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;全量构建指的是针对代码仓库中所有的代码进行构建；&lt;/li&gt;
&lt;li&gt;增量构建是指只针对有变动的代码及受变动影响的相关代码进行重新构建。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从定义看，增量构建要做的事情和精准测试要做的事情几乎是一样的。只不过，把build命令，换成test命令罢了。&lt;/p&gt;
&lt;p&gt;这也就是为什么我觉得应该把“精准测试”叫做“增量测试”才对。&lt;/p&gt;
&lt;p&gt;目前行业里，在增量构建领域，Bazel可谓是佼佼者。&lt;/p&gt;
&lt;h2 id=&#34;bazel介绍&#34;&gt;Bazel介绍&lt;/h2&gt;
&lt;p&gt;Bazel是Google 2015年开源的一款构建工具。采用声明式的方式定义所有的构建任务。Bazel叫target。&lt;/p&gt;
&lt;p&gt;每个target声明包含了：构建类型、输入、构建方式、输出、依赖等。以下代码展示了两个构建任务：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 声明打成jar包，作为library被其他任务使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;java_library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;greeter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;srcs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;src/main/java/com/example/Greeting.java&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 声明打包成一个可执行Jar&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;java_binary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ProjectRunner&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;srcs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;src/main/java/com/example/ProjectRunner.java&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;main_class&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;com.example.ProjectRunner&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 依赖之前打好的library，这是实现增量构建的关键&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;deps&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;:greeter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Bazel在运行时，就会根据target声明，在内部维护一个有向依赖图，如下：
&lt;img loading=&#34;lazy&#34; src=&#34;https://showme.codes/assets/images/dag-bazel2.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;有了这个有向依赖图，Bazel就可以实现增量构建。&lt;/p&gt;
&lt;p&gt;当用户修改了 Greeting.java 文件时，Bazel知道 //:greeter target 依赖它，所以Bazel知道要执行 //:greeter 时。同时Bazel又知道 //:ProjectRunner 依赖 //:greeter ，所以Bazel知道还要执行 //:ProjectRunner target。&lt;/p&gt;
&lt;p&gt;以上是在同一个语言下的增量构建的案例，让我们看下多语言场景下，Bazel是如何实现增量构建的。&lt;/p&gt;
&lt;h2 id=&#34;多语言场景下bazel是如何实现增量构建的&#34;&gt;多语言场景下Bazel是如何实现增量构建的&lt;/h2&gt;
&lt;p&gt;如下图，在一个软件工程下，同时使用到了：Docker、Python、YAML、C++等技术。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://showme.codes/assets/images/bazel-test2.png&#34;&gt;
这个依赖关系是在开发和运维在写代码的时候就定义好了的。所以，Bazel从一开始就有了这个依赖图。&lt;/p&gt;
&lt;p&gt;Bazel允许声明不同语言的target之间的依赖，所以，很自然的，一个软件工程的完成的依赖图就有了。你不需要花额外的精力去收集。&lt;/p&gt;
&lt;p&gt;当执行Bazel进行构建build时，Bazel发现配置文件config.yaml是被修改了，这时它就计算出接下来要执行的构建，如下图标为橙色的路径。即所有的依赖于//:config.yaml 的直接依赖和间接依赖。&lt;/p&gt;
&lt;p&gt;但是，因为执行的是build，所以，Bazel只会build路径上的所有源代码，并不会去执行 &lt;code&gt;*_test&lt;/code&gt; 测试任务。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&#34;lazy&#34; src=&#34;https://showme.codes/assets/images/bazel-test.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;这就是精准构建，不，叫增量构建：只构建需要构建的。&lt;/p&gt;
&lt;p&gt;也许你会好奇Bazel是怎么做到的？请关注我的公众号，将来我还会分享更多Bazel的内容。&lt;/p&gt;
&lt;h2 id=&#34;bazel是如何精准测试&#34;&gt;Bazel是如何精准测试&lt;/h2&gt;
&lt;p&gt;Bazel有很多子命令，有两个常用的子命令，一个是&lt;code&gt;build&lt;/code&gt;，一个是&lt;code&gt;test&lt;/code&gt;。这两个子命令是用于区分构建的类型的。因为有时，你可能只是想build，不想test。&lt;/p&gt;
&lt;p&gt;接着上面的例子，同样修改了config.yaml文件，当我们执行的是test子命令，Bazel会计算出要执行的路径——和上文一样的路径，因为//:config.yaml所影响的依赖范围是一样的。&lt;/p&gt;
&lt;p&gt;区别是，这次它除了执行build，还会运行&lt;code&gt;*_test&lt;/code&gt;类的任务。Bazel并不会关心它是单元测试，还是集成测试，只关心该测试的大小。如下图中的标为黑色的部分：
![](/assets/images/Screen Shot 2023-11-02 at 9.30.45 PM.png)&lt;/p&gt;</description>
    </item>
    <item>
      <title>精准测试是个错误</title>
      <link>https://showme.codes/zh-cn/2023-04-21-accuration-testing-is-wrong/</link>
      <pubDate>Fri, 21 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://showme.codes/zh-cn/2023-04-21-accuration-testing-is-wrong/</guid>
      <description>&lt;p&gt;如果你已经了解了精准测试在行业的主流做法，你可以跳过相关内容。&lt;/p&gt;
&lt;h2 id=&#34;行业里对于精准测试的定义&#34;&gt;行业里对于精准测试的定义&lt;/h2&gt;
&lt;p&gt;在网上流传着一些精准测试的定义（如果你对这些定义不感冒，可直接跳到我个人的定义）：&lt;/p&gt;
&lt;p&gt;自网易陈逸青（2020）的定义：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;借助一定的技术手段、通过辅助算法对传统软件测试过程进行可视化、分析及优化的过程，使得测试过程更加可视化、智能、可信和精准。 原文：https://www.infoq.cn/article/xuu91crqa4hcjz8uomjs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;来自HSBC的测试咨询专家齐磊（2021年）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;通俗点讲：核心基于源代码变更分析，结合分析算法，确定影响范围，提升测试效率。 原文：https://www.infoq.cn/article/2feiv8a5kogaqlbzwosh&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;来自星云测试（2022年）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;精准测试一句话概括就是：测试用例和代码之间的追溯，这是它最本质的东西。精准测试的本质决定了它抓住了测试的一个核心要点。 原文： &lt;a href=&#34;https://testerhome.com/topics/34557&#34;&gt;https://testerhome.com/topics/34557&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;来自得物技术（2023年）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;精准测试是基于源代码变更分析，结合一些分析算法，从而确定改动代码影响的范围，设计测试用例进行针对性测试，一方面可以提升测试效率，另一方面精准测试还可以将测试用例与程序代码之间的逻辑映射关系建立起来， 而这个过程则是通过工具去采集测试过程执行的代码逻辑及测试数据。这两个点也正是精准测试的核心：正向追溯和逆向追溯。原文： &lt;a href=&#34;https://tech.dewu.com/article?id=43&#34;&gt;https://tech.dewu.com/article?id=43&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;以下是来自网易严选的架构图：&lt;/p&gt;
&lt;p&gt;![](/assets/images/网易严选的架构图1.png]]&lt;/p&gt;
&lt;h2 id=&#34;我个人的定义&#34;&gt;我个人的定义&lt;/h2&gt;
&lt;p&gt;在笔者看来，精准测试的定义应该是这样的：它是一种能力，能只针对变更进行测试，而不是每次变更都进行全量测试。注意，我指的是“变更”，而不只是“代码变更”，也就是说所有类型的变更，包括手动变更。&lt;/p&gt;
&lt;p&gt;精准测试的思路并不复杂，分成三个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找到变更；&lt;/li&gt;
&lt;li&gt;根据变更找到相关联的测试用例；&lt;/li&gt;
&lt;li&gt;只执行相关联的测试用例。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;其实，把这种方法叫&lt;strong&gt;增量测试（Incremental Testing）&lt;/strong&gt; 更准确，更合适。毕竟你是针对增量的代码变更进行测试。&lt;/p&gt;
&lt;p&gt;如果不是针对增量变更进行测试，你也能只执行一个你想测试的测试。难道这样不算精准测试吗？&lt;/p&gt;
&lt;h2 id=&#34;国内行业主流的实现精准测试的方法&#34;&gt;国内行业主流的实现精准测试的方法&lt;/h2&gt;
&lt;h3 id=&#34;步骤一找到代码变更&#34;&gt;步骤一：找到代码变更&lt;/h3&gt;
&lt;p&gt;通过commit之间进行差异对比​。​&lt;/p&gt;
&lt;h3 id=&#34;步骤二根据代码变更找到相关联的测试用例&#34;&gt;步骤二：根据代码变更找到相关联的测试用例&lt;/h3&gt;
&lt;p&gt;要做到“根据代码变更找到相关联的测试用例”，我们就必须知道代码与测试用例之间的关系。&lt;/p&gt;
&lt;p&gt;获取这个关系的做法是在执行测试的同时，做以下事情：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;将流量记录下来；&lt;/li&gt;
&lt;li&gt;将因流量而执行地代码的调用链记录下来；&lt;/li&gt;
&lt;li&gt;将测试用例的元数据与代码调用链的关系记录下来；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个过程就完成了对被调用代码与测试用例之间的映射关系的建立。&lt;/p&gt;
&lt;p&gt;另，现实往往存在很多未被测试用例覆盖到的代码，这时，通过静态代码分析和测试覆盖率计算技术结合，生成未被测试到的代码的报告。&lt;/p&gt;
&lt;p&gt;可以看出，通过以上方式“找出代码与测试用例之间的关系”的成本是极高的。所以，在这个领域会有：引流平台、测试用例管理平台、精准测试平台等等平台。这也给大家一个感觉，我们要先有一个平台才能做到精准测试。&lt;/p&gt;
&lt;p&gt;说到底就是通过插桩技术，构建代码的执行路径，并找到​对应的测试用例之间关系。&lt;/p&gt;
&lt;p&gt;目前在网上目前看到大多还只是针对Java语言或者C++来实现精准测试，其它的语言目前没有见到。&lt;/p&gt;
&lt;h3 id=&#34;步骤三只执行相关联的测试用例&#34;&gt;步骤三：只执行相关联的测试用例&lt;/h3&gt;
&lt;p&gt;当有了代码与测试用例之间的关系，只执行相关联的测试用例就简单很多了。&lt;/p&gt;
&lt;h2 id=&#34;主流方法的坑&#34;&gt;主流方法的坑&lt;/h2&gt;
&lt;p&gt;以下是齐磊总结的精准测试存在的问题：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;基于手工测试的精准测试建立映射关系繁杂，如果需求改变频繁，用例维护以及之间的关系维护需要耗费大量时间精力。&lt;/li&gt;
&lt;li&gt;精准测试需要一定的自动化测试的覆盖，这样做起来更有意义，例如 api 自动化测试，如果本身用例过少，与代码之间关联关系不多时，变更代码后可能不会得出什么结果。&lt;/li&gt;
&lt;li&gt;最好有对应的用例管理系统，能够方便的帮助我们建立与代码之间的关系。&lt;/li&gt;
&lt;li&gt;需要投入开发能力强的 QA 或者测试开发建立整套系统环境，但长远考虑，将精准测试嵌入整个公司的质量平台中，不管对于新项目还说维护项目来说都是一种提升。&lt;/li&gt;
&lt;li&gt;项目生命周期需要较长，短期项目花费巨大精力开发和维护整套精准测试系统得不偿失。短期项目可以利用精准测试以 api 测试覆盖率作为衡量标准。不去建立繁杂的关系，只监控 UI API 测试覆盖率迭代时的变更来达到目的。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是，个人认为齐磊总结的内容没有问题，的确都是坑。但是那些不是精准测试的坑，而是国内行业主流的实现方式的坑。直白地说就是喝水时，喝水的角度错了。&lt;/p&gt;
&lt;h2 id=&#34;为什么主流实现方法从方向上就是错的&#34;&gt;为什么主流实现方法从方向上就是错的&lt;/h2&gt;
&lt;p&gt;为什么我认为以上地坑是由实现方法导致的？以下是我的论点，欢迎讨论指正：&lt;/p&gt;
&lt;h3 id=&#34;该方法只局限于单一语言&#34;&gt;该方法只局限于单一语言&lt;/h3&gt;
&lt;p&gt;准确来说，精准测试不应该只针对代码的变更，而是所有的变更。更不应该只针对单一语言的变更，而是可以针对所有的语言。&lt;/p&gt;
&lt;p&gt;因为精准测试的定义本身不局限于某种语言的代码变更，而是对一个软件工程中所有的变更而言。一次SQL的变更，你是否需要精准的知道要执行哪些测试？一个前端的CSS代码的变更，你是否需要精准的知道要执行哪些测试？&lt;/p&gt;
&lt;p&gt;目前行业里主流的方法，只是针对单一语言下的场景而设计的。按同样的思路是无法做到多语言的。我说的多语言指提同一工程下的多语言，不是指相互独立的单语言工程。&lt;/p&gt;
&lt;h3 id=&#34;只能在平台上做精准测试&#34;&gt;只能在平台上做精准测试&lt;/h3&gt;
&lt;p&gt;即，我们首先需要一个平台，才能做到精准测试。&lt;/p&gt;
&lt;p&gt;但我们希望在开发者本地开发环境就可以做到精准测试。&lt;/p&gt;
&lt;h2 id=&#34;最后&#34;&gt;最后&lt;/h2&gt;
&lt;p&gt;文章标题并不是说“精准测试”本身是一个错误，是想说上述的实现方法是一个错误方法。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
