专注测试技术的课程订阅站点

什么是向量数据库

对于向量数据库有疑问吗?以下是对这个数据库的简要解释。

什么是向量?

向量是一组数字的数组,表示点在空间中沿多个维度的位置。例如,向量{12, 13, 19, 8, 9}表示一个点在 5 个维度上的位置。向量可以几何地表示数据,使得数据点之间可以进行数学比较。

向量与嵌入有什么关系?

在机器学习中,嵌入是表示数据点(如单词、句子、图像等)的向量。嵌入将数据的语义含义编码为向量形式。它们由经过训练的神经网络生成,这些网络将数据点映射到有效的向量表示。这些嵌入将相关概念放置在向量空间中靠近的位置。

向量数据库如何工作?

向量数据库存储了各种数据点(如文档、图像、产品等)的嵌入,并将这些嵌入映射回其原始数据。数据库可以基于向量的相似性进行快速的相似性搜索。查询嵌入可以与存储的嵌入进行比较,最相似的向量可以几乎即时地被检索出来。这为语义搜索、推荐和其他人工智能应用提供了支持。

向量数据库在人工智能中的应用是什么?

向量数据库具有几个关键的人工智能应用:

  • 语义搜索 - 基于含义而不仅仅是关键词来检索信息
  • 推荐 - 提供与用户兴趣最相关的内容
  • 大型语言模型 - 理解上下文中的单词,用于生成和摘要
  • 异常检测 - 识别与正常情况相比的异常数据点
  • 图像分类 - 基于视觉属性对图像进行分类

通过促进快速的相似性比较,向量数据库使得机器学习模型能够在数据之间建立联系。这支持了使用原始数据无法实现的高级人工智能功能。向量空间充当算法构建理解的一种"记忆"。

移动测试指南

Guide to Mobile Testing

移动应用已经风靡全球,在移动互联网如此普及的今天,移动测试的重要性不言而喻。个人认为移动应用现在是大部分互联网公司的主要业态,在竞争激烈的现时,移动应用的质量可能会影响某个产品的成败与存亡,在去测试化思潮如此普遍的今天,移动端应用应该是最不可能砍掉测试人员的。因为

  • 移动应用的质量是第一大事
  • 竞争越激烈,好的质量越重要
  • 测试移动应用的效率目前还是偏低,用高薪的开发人员去兼任测试职能有点得不偿失
  • 移动端更新成本相对较高,测试充分再发出去才能尽可能地规避更新应用进行 bugfix 的风险

诚然,有些公司在推进去测试化,但那些公司可能是

  • 所在行业垄断性质明显,没有其他公司可以进行正面竞争,比如微软
  • 公司和用户对线上问题忍耐度相对较高,应用形态相对单纯,试错成本相对较低,比如之前的头条
  • 行业已过高速增长期但存量竞争激烈,产品基本处于维护阶段,不需要投入太多的开发和测试资源,比如腾讯的某些产品

从这里开始就是翻译了,原文地址在:https://medium.com/@iamfaisalkhatri/guide-to-mobile-testing-d0dd2d9b59f1

所以大部分情况下,移动端的测试以及质量提升是需要专职测试人员进行负责和统筹的,所以不必焦虑。相反,了解一些基本的移动端测试知识是一件较为必要的事情。

质量是关键

我们需要检查所有内容以及所有可能的排列和组合,以免出现任何 bug。由于移动设备也存储了最终用户的个人数据,因此有必要对安全性和数据完整性进行检查。

测试应用程序的性能同样重要,因为如今人们对应用程序的速度更感兴趣。如果功能能用,但应用响应时间过长,可能无法吸引用户。因此,应用程序的性能测试也是需要考虑的重要因素。

谈到测试移动应用程序,我认为我们应该首先弄清楚测试策略,因为它可以帮助我们分解测试阶段并进行高质量的测试,并帮助我们避免漏测一些重要内容。

定义测试策略

首先我们需要弄清楚移动应用的类型

  • 原生应用:离线可以直接用安装包进行安装,一般情况下可以在应用商店下载
  • 移动 web 应用:比如 h5 应用,基本是用 html+css+js 进行开发的,可能长得跟原生应用很像,但基本上不是一回事
  • 混合应用:既有原生也有移动 web 的应用,一般情况下对开发人员比较友好,毕竟 web 应用比原生应用开发要容易一点点

我们以混合应用为例在说明一下如何定义我们的测试策略,在进入细节之前,我们先来了解一下测试类型的相关知识。

测试类型

理想情况下,虑到混合应用程序,我认为应该考虑以下测试类型

  1. 功能测试。
  2. 性能测试
  3. 安全测试
  4. 可用性测试
  5. UI/UX 测试

%E7%A7%BB%E5%8A%A8%E6%B5%8B%E8%AF%95%E6%8C%87%E5%8D%97%2031ddadb1681b4287803ef98d6ca78960/Untitled.png

何时以及如何开始测试

由于我们处于当今软件世界虔诚地遵循敏捷的时代,因此最好尽早开始测试。

测试应该在软件开发生命周期的每个阶段进行,而不仅仅是在功能完全开发时进行。

话虽如此,请始终确保开发人员正在编写单元测试。还应涵盖集成和服务层测试。只写测试没有帮助,代码覆盖率报告应该显示单元测试覆盖率至少大于 80%,如果有可能的话,可以逐渐增加到 100%。有一条流水线可以帮助我们轻松监控生命周期并在每个阶段采取纠正措施,这很好。因此,除非构建是绿色的,否则继续进行测试并尽快进行所需的修复是不好的。

测试计划

有一个测试计划是很好的,因为它会更容易检查所有的测试活动,所以我们不会遗漏任何东西,顺利地执行测试并提供高质量的输出。

第一个也是最重要的情况是用户是否能够使用 PlayStore/App Store 成功安装应用程序。

Selenium Manager使用指南

Selenium 社区最近发布了 Selenium Manager 工具,主要是解决每隔一段时间就要重新去下载 driver 的痛点。当然了,这也是我痛点。因为 chrome 浏览器会自动更新的关系,之前我都是关掉自动更新从而回避去下载新 driver 的问题,不过因为用户的版本大多都是较新的,所以测试浏览器每隔一段时间还是要更新一下才比较好。我自己试用了一下,感觉还是很不错的,非常有意思的一个点是 sm 竟然是 rust 开发的,在我的印象里这种对性能和稳定性要求不是特别高的命令行用 go 开发和维护的话效率可能会更高一点。下面是官方 blog 的翻译以及我自己的一点点体验。

大多数人使用 Selenium 的第一次经验都会出现这样的错误消息:

java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://chromedriver.chromium.org/. The latest version can be downloaded from https://chromedriver.chromium.org/downloads

然后他们不得不在网上搜索有关如何处理他们下载的驱动程序的说明。

Selenium:现在已经内置了驱动程序!

Selenium 项目希望改善用户体验,其中一项首要任务是帮助所有用户简化他们设置环境的方式。多年来,配置浏览器驱动程序一直是用户需要执行的任务,以便运行 Selenium。

设置一次浏览器驱动程序并不那么复杂,但随着浏览器发布周期缩短,现在每 4-6 周就有一个新的 Chrome/Firefox/Edge 版本,使得保持浏览器驱动程序与浏览器版本同步的任务变得不那么容易了。

Selenium Manager 是一个新的工具,可帮助轻松获得运行 Selenium 所需的工作环境。如果 Chrome、Firefox 或 Edge 不在 PATH 中,Selenium Manager Beta 1 将配置它们的浏览器驱动程序。

确认:代码覆盖率是一个无用的管理指标

看标题就知道这篇文章很有意思,作为一个之前专注过做代码覆盖率平台的人,这个观点一直模模糊糊是存在于我的心里的,不过从来没有这么直截了当的说出来,这篇文章的作者有理有据,值得一看。原文在这里: https://drpicox.medium.com/confirmed-code-coverage-is-a-useless-management-metric-35afa05e8549,我只做了一些翻译。

有一种强烈的信念,即代码覆盖率是衡量软件产品质量的重要指标,这个信念多年来一直被技术领导者们毫无疑问地共享。从表面上看,这个理论似乎很有道理:测试越彻底,代码覆盖率越高,因此我们的软件应该更加健壮和无错误。这个观念已经深深植入我们的思维中。但是,如果我能证明代码覆盖率从根本上是错误的呢?如果我能向你展示一个如此简单的想法,让你对此毫无疑问?所以,请做好准备,做好心理准备。

鉴于本文仅展示了哪些指标不适用于管理(尽管对开发人员非常有用),但并未说明应该遵循哪些指标,因此我最近写了一篇后续文章,解释了应该使用哪四个基本指标以及为什么要这样做,这些观点都有科学依据

The Code Coverage 代码覆盖率

代码覆盖率,简单来说,是衡量你的代码有多少被测试所“触及”或“覆盖”的一种度量。我们假设在我们的产品中有测试,并且我们至少在每次发布之前运行这些测试。当这些测试执行时,它们会对产品进行操作,从而使代码执行。很快,我们意识到如果我们追踪哪些代码被测试执行,我们就可以开始衡量有多少代码被执行了。我们将执行的代码与产品中的总代码量的比例称为“代码覆盖率”。

code coverage = executed code by tests / size of the code

这是一个非常简单的度量标准。如果我们有 100 行代码,但测试只执行了其中的 75 行,那么我们的代码覆盖率为 75%。

很快我们意识到了更重要的事情。如果代码覆盖率不是 100%,那就意味着我们的测试没有执行到某些代码,换句话说:我们有未经测试的代码!

因此,拥有未经测试的代码是危险的,因为它可能包含错误。此外,它还可能包含业务关键功能,如果我们触碰到该代码,我们可能会丧失这些功能。

所以,拥有高代码覆盖率是必须的。

代码覆盖率的谬论

但是,现在我们面临一个谬论:我们知道揭示代码意味着我们的测试遗漏了重要的情况,但反过来并不成立。

例如,在之前的例子中,我们的代码覆盖率为 75%。换句话说,这个指标表示有 25%的代码行没有被任何测试执行过,这明确指出了一个风险区域。我们可以确定地说,这 25%的代码库没有经过任何测试验证,因此可能成为问题和维护困难的滋生地。

然而,这就是我们冒险陷入谬误的时候:虽然我们可以自信地说未经测试的代码隐藏了潜在的错误和对未来发展的阻碍,但我们可能相信相反的情况是真实的。我们可能相信代码覆盖意味着它有更少的错误和更少的维护问题。但是,这只是一个直觉,甚至可能看起来很合乎逻辑,但事实证明这并不正确。

事实是,我们可以实现 100%的代码覆盖率,但代码仍然可能存在大量的错误,并且难以维护。

一个基本的例子

想象一个简单的函数,它计算两个数字的和:

function addition(a, b) {
  return a + b;
}

哪个是能够覆盖 100%的最简单的测试?只需添加一个附加项即可使所有代码执行:

test('the addition function', () => {
  addition(3, 4);
});

这个测试覆盖了 100%的代码。然而,它是无用的。为什么呢?如果我们将加法的实现改为这样一个:

function addition(a, b) {
  return a - b;
}

测试仍然通过!

Postman越来越难用了

今天看到有个哥们吐槽 postman 的新版界面,这位是 Spotify 的资深工程师,所以他的槽点还是有些代表性,他是这么说的

Uhhhh what happened to Postman? I just want to send, and inspect http requests?

What is all this shit?

Adam Rackis Senior Web Engineer at Spotify. Prev, Riot. Next, React, Svelte, C++ when I’m feeling nasty. Beer, whiskey, coffee snob. Book lover. Jr Developer for life. https://github.com/arackaf

怀着看热闹不嫌事大的心情,我把本机的 postman 更新了一下。对于更新这件事情我是能不更就不更,因为我一直觉得 postman 的旧版本就是比新版本要好用。

更新到最新版本之后,有趣的事情发生了,界面确实变化很大,之前 postman 的核心就是请求构造页面,现在我随便点了几下,结果 postman 频繁弹出登录页面,我大概点了 2 个菜单,分别是 Home 和 Explore,登录框弹出来 3 次,最无语的是在 home 页面的全屏登录框,我一时半会找不到 X 按钮,当时让我无比的慌乱,不登录难道就不配用你吗?幸好在一个不起眼的地方看到可以忽略登录的链接,终于让我这种不愿意透露姓名的 postman 忠实用户有了继续使用的权利。

string算法之二进制加法

最近寒风凛冽,估计不少同学都在刷算法题了,这里给大家介绍一个 python 实现的算法仓库,里面有很多常见算法的实现,有兴趣的同学可以先通过既有算法学习,掌握一些套路之后再由易到难把题刷起来。仓库地址:https://github.com/keon/algorithms

先给大家分享一个二进制加法的算法吧。

题目

输入:2 个二进制的字符串

输出:也以二进制的方式返回相加后的结果

比如

a = "11"
b = "1"
Return "100"

分析

这道题看完之后我基本上没有任何思路,丝毫没有一点点挣扎,直接看答案了。

实现

def add_binary(a, b):
    s = ""
    c, i, j = 0, len(a)-1, len(b)-1
    zero = ord('0')
    while (i >= 0 or j >= 0 or c == 1):
        if (i >= 0):
            c += ord(a[i]) - zero
            i -= 1
        if (j >= 0):
            c += ord(b[j]) - zero
            j -= 1
        s = chr(c % 2 + zero) + s
        c //= 2

    return s

看完以后发现实现思路非常的精妙。

首先确定’0’这个字符的 ascii 码,zero 的值就是整形的 48。

下面遍历两个字符串的每一位,从低位到高位,如果当前位存在的话,则取这一位的 ascii 码减去 zero,因为是二进制,所以当前位的值要么是 0 要么是 1,所以每次遍历相减后得到的结果要么是 0 要么是 1,这就等于是把当前位从字符转成了二进制。所以后面如果有类似的字符或字符串转成二进制的题,可以参考每一位减去 ascii 0 的实现方式。

取一个数 c,保存两个字符串当前位的和,所以 c 的取值一定是固定的

  • 无进位的情况
    • c = 1 + 1 = 2
    • c = 1 + 0 = 1
    • c = 0 + 1 = 1
    • c = 0 + 0 = 0
  • 有进位,c 就等于 1
    • c = 1 + 1 + 1 = 3
    • c = 1 + 0 + 1 = 2
    • c = 0 + 1 + 1 = 2
    • c = 1 + 0 + 0 = 1

好了,下面再用 c 去模 2,在 c = 2 或者是 0 的时候,就可以得到当前位的值是 0,c 是 1 或 3 的时候当前位就是 1,这里用取模的方式实现了二进制的加法,简单却深刻和优雅。