e2e 测试是不是应该将数据保存在真实数据库中?

Posted

技术标签:

【中文标题】e2e 测试是不是应该将数据保存在真实数据库中?【英文标题】:Should e2e tests persist data in real databases?e2e 测试是否应该将数据保存在真实数据库中? 【发布时间】:2019-08-01 05:53:15 【问题描述】:

我已经阅读了很多关于 e2e 测试的内容,但我无法理解的一件事是 e2e 测试应该有多“真实”。

无论我在 e2e 测试中使用什么工具,我都发现它们大部分时间都在本地、开发或 alpha 环境中运行。

如果我的应用程序具有身份验证,我应该在数据库中创建一个具有有效凭据的“测试”用户吗?我应该为 Alpha 甚至生产环境这样做吗?这个测试用户如何登录我的应用程序?

假设我有臭名昭著的 TODO 应用程序。我有一个让用户登录的测试。登录后,我想测试用户是否能够创建 TODO。此 TODO 保存在数据库中。

运行测试后,我应该运行一些东西来删除 e2e 测试期间创建的数据吗?或者我应该在保存请求之前拦截请求并模拟响应(这是否是 e2e 测试的反模式)?

【问题讨论】:

【参考方案1】:

端到端测试涉及确保应用程序的集成组件按预期运行。整个应用程序在真实场景中进行测试,例如与数据库、网络、硬件和其他应用程序进行通信

Definition of Technopedia

E2E 测试是最抽象的测试。它测试集成组件的“流量”和“完整性”。或多或少,作为测试,它是一个完整的黑盒,所有部件都应该可以互换。集成测试,检查代码组件是否可互换。 E2E 在测试层级(nginx 或 Apache?php 或 Java?Ms 或 mysql?)中高出一步。

此外,E2E 测试的定义是业务需求的直接转换,并且或多或少由需求工程流程预先定义。

例如,Gherkin 是一种将用例转换为功能和场景的语言。示例:

Feature:  Login functionality of social networking site Facebook. 
Given:  I am a facebook user. 
When: I enter username as username. 
And I enter the password as the password 
Then I should be redirected to the home page of facebook 

一个用例/功能本身可能包含几个或多个句子,具体取决于主题的复杂性。无论如何:它应该完全独立于您的应用程序。

如何处理测试取决于您,并且取决于您的应用程序:

您可能会捕获某些情况(注册用户?)或者您可能想使用每日 Cron 清理数据库?

另外,为每个功能编写测试对性能要求很高。大多数时候,您为演练(您的应用程序最重要的部分 - 资金来自哪里)或功能编写这些测试,这些测试非常重要,但从未主动测试过(cookie 信息、退订电子邮件、法律信息等) .)

【讨论】:

【参考方案2】:

我目前在一家大型知名公司的测试工具和框架团队工作。所以虽然我不是专家,但这是我工作的一部分。我将专门讨论 Web 测试。对于 iosandroid 等原生应用的测试有些不同,我对这些方面不是很熟悉。

e2e(端到端)和集成测试之间的术语在某种程度上可以互换,而单元测试有更具体的定义。

一般来说,e2e/集成测试应该可以在开发和生产环境中运行。根据您的设置,您的开发环境可能正在使用生产数据库的一些半频繁更新的快照。在其他情况下,您的本地环境可能会影响实际的生产数据库。这两种方法各有利弊,但这在很大程度上取决于您的公司或项目的规模。例如,如果您在一家拥有专门团队的大公司工作,那么您每天可以看到生产数据库发生许多变化,而在小型团队中,每周生产数据库的快照可能足以在本地进行测试。 一世 在基础级别,所有集成测试都应该被视为真实的。在处理 Web 应用程序时,我们必须考虑许多其他因素,例如不同的 Web 浏览器、网络活动/可用性等。因此,模拟 api 调用的数据将允许超快速测试,但会增加另一层复杂性确保模拟与真实世界的数据库保持同步。

在本地运行集成测试应该或多或少地对您的开发服务器做同样的事情,就像他们将对登台和生产做的事情一样。除了让应用检测其是否在开发、登台或生产环境中运行以切换 URL 和各种凭据之外,应用的行为方式应该完全相同。

关于您关于身份验证的问题,答案是肯定的。让我们看两个显示不同考虑因素的示例。

假设您的项目非常小。您在生产环境中创建了一些真实帐户,并且您的数据库每周都会被快照,以便在本地开发环境中使用。您只需根据需要与这些用户中的一个或多个运行集成测试。由于本地测试只针对您的本地数据库,因此您无需担心生成的数据,因为它不会影响生产。您团队中的其他工程师可以使用相同的用户而不必担心。如果一位工程师对数据库架构、ORM 等进行了一些更改,那么每个人都会获得数据库快照的新副本并继续工作。

现在来说另一个极端。假设你的项目很大。每天都有数百万用户和数百名员工共同对代码库和数据库进行更改。有各种方法可以设置基础设施来处理各种工程任务。数据太多,数据库更改太频繁,无法使用本地快照。在这种规模下,您可能正在进行持续集成并在每次提交时运行您的测试。您希望这样做,以使传入的更改不会进入生产环境并导致重大问题。您可能正在针对不断更新的暂存数据库,甚至可能针对您的生产数据库本身运行本地开发环境。 (尝试规划暂存数据库,因为它可以避免很多其他问题。)

现在,只有一小部分专门的测试用户开始成为问题。测试一直在运行,无论是自动化的还是由数十名工程师都在自己的工作中进行的。由于暂存数据库可能是共享的,因此您很容易开始遇到奇怪的冲突,因为同一个测试用户正在做各种各样的事情并开始导致测试失败。我见过的一个很好的解决方案是一种测试帐户结帐服务器。您创建了 100 个或 1000 个(或更多)测试用户帐户。当您的集成测试运行时,他们会从服务器上签出一个测试用户帐户。测试完成后,集成测试会清理他们对该用户所做的任何更改,并告诉结帐服务器该用户再次空闲。然后它随机被某人/其他人签出并继续循环。

因此,与您的问题直接相关的要点:

    您应该始终拥有与普通用户帐户完全相同的专用测试用户帐户,仅用于测试。 根据团队和项目的规模,如果是少数几个专用帐户就可以了。如果在更大范围内工作,您需要更多专用测试帐户,并且可能需要允许单独测试运行以根据需要结帐用户的自动化服务。 测试应始终自行清理。如果测试创建了一个存储在数据库中的 TODO。当测试完成运行时,应该从数据库中删除该 TODO。如果您对此不持一致意见,您最终会遇到数据不一致的错误和问题。上帝禁止在生产中发生这种情况。 只需担心单元测试的模拟数据,除非您在一个非常好的和专用的工程环境中工作,在那里您有专门的人员致力于使数据库模拟始终保持最新状态。如果您可以这样做,那么您的集成测试将会非常快,而且您真的不必担心数据库的问题。但是,如果没有专门的支持,随着时间的推移很难保持这种状态。

【讨论】:

“有时无法恢复原样”。 medium.com/how-we-build-fedora/…【参考方案3】:

我已经阅读了很多关于 e2e 测试的内容,但我无法理解的一件事是 e2e 测试应该有多“真实”。

E2e 应该尽可能地模仿生产系统,更重要的是,您可以使用 e2e 自动化来重现任何生产问题,如生产数据,

无论我在 e2e 测试中使用什么工具,我都发现它们大部分时间都在本地、开发或 alpha 环境中运行。

e2e 自动化必须适用于任何资源/数据库/datatsore/消息总线等,以及任何环境,包括本地/远程或云平台

如果我的应用程序具有身份验证,我应该在数据库中创建一个具有有效凭据的“测试”用户吗?我应该为 Alpha 甚至生产环境这样做吗?这个测试用户如何登录我的应用程序?

只要应用凭据是应用配置的一部分,您就可以灵活地控制专用于测试的凭据。我强烈建议运行并行的全自动 e2e 专用基础设施,它不会泄露或共享生产机密。

假设我有臭名昭著的 TODO 应用程序。我有一个让用户登录的测试。登录后,我想测试用户是否能够创建 TODO。此 TODO 保存在数据库中。

通过 e2e 测试,您有兴趣识别所有应用输入(如 UI 交互或 REST/HTTP 请求)、配置文件和带有验证规则的输出。这包括 UI 更改、生成的日志/消息、数据存储/数据库更改。

运行测试后,我应该运行一些东西来删除 e2e 测试期间创建的数据吗?或者我应该在保存请求之前拦截请求并模拟响应(这是否是 e2e 测试的反模式)?

作为 e2e 测试的一部分,您需要注意设置初始应用程序状态,以及每个用例的状态(如果适用)。通过 e2e 测试,您希望测试所有应用程序行为,因此这里没有太多可以模拟的地方。运行测试后可以销毁所有应用资源,服务清空数据库。我相信这是可选步骤,因为设置应用程序或用例状态涉及资源/数据库准备。

最后,如果您没有正确的工具集和良好的数据组织策略,e2e 测试可能会很有挑战性,尤其是随着时间的推移,您最终会针对中小型应用程序进行数百个用例测试。除此之外,您还需要能够与用任何语言(java、javascript golang 等)编写的多堆栈应用程序一起工作的 e2e 测试工具,并支持任何平台的自动化,包括 localbox、docker、kubernetess、无服务器云。

以下是一些有趣的读数:

Data testing strategy ETL partical e2e testing Practical e2e testing examples Serverless e2e practical examples

【讨论】:

【参考方案4】:

以下是我们的测试工作方式。这种程度的努力在许多组织中可能不可行,但我确实认为它运作良好。相对于您最初的问题,我认为,在可能的情况下,使用真实的东西而不是模拟,例如,使用如下所述的真实数据库。

基本架构

Sql 服务器数据库 C# 中间件 角前端

完整的 CI/CD 已到位。 CI 在 docker 容器中运行。每次推送都会运行整个测试策略(UAT 测试除外)。

中间件

单元测试: 类级别测试。 数据库连接指向内存中的实现。 使用 NSubstitute 模拟依赖类。 集成测试: 我们的基础服务库有一个测试配置基础设施,允许模拟: 其他外部 http 服务。 内部服务。 身份验证对象(用户、令牌等)。 通过依赖注入通过接口的任何其他实体。 数据库 运行测试的 docker 容器引用了另一个包含 SqlServer for linux (mcr.microsoft.com/mssql/server:2017-latest-ubuntu) 的容器。 因此,测试针对真实数据库运行。 该服务拥有一个脚本列表,无论在何处启动(不仅仅是在 CI 中),它都会根据需要执行这些脚本。因此,在每次 CI 运行期间,它都会播放整个历史记录。然而,这非常快,因为数据库开始时是空的。 此测试策略的漏洞在于性能测试。 测试配置初始化设置连接字符串到这个本地数据库。 真正的服务启动,配置测试。

前端

标准的角度单元/组件测试通过角度工具 + 业力运行。

端到端

Cypress 是使用的框架。 中间件和前端均已启动。从这里开始的中间件的配置方式与上述中间件测试下的集成测试相同(相同的入口点)。 有一些外部服务调用发生在我们无法直接控制的范围内。我们使用 cypress 钩子来防止这些调用发生。

UAT 测试

产品所有者在发布之前进行的手动测试。

【讨论】:

以上是关于e2e 测试是不是应该将数据保存在真实数据库中?的主要内容,如果未能解决你的问题,请参考以下文章

数据库基准测试中应该避免的错误

Protractor E2E - 您如何管理数据库?

我可以在 Spring Boot 中测试我的存储库而不实际将测试数据保存在数据库中吗?

使用带有 Angular2 和 Socket.io 的量角器运行 e2e 测试

使用 prisma graphql api 在嵌套 js 中进行 e2e 测试

angular 调试 js (分 karms protractor / test e2e unit )