首页 > 其他分享 >分层测试以获得对代码的信心

分层测试以获得对代码的信心

时间:2023-03-12 17:31:36浏览次数:47  
标签:代码 单元测试 应用程序 分层 objects 测试 编写 hello

image.png

令我震惊的是,很少有开发人员了解综合测试。

我经常收到开发人员发来的电子邮件,担心他们缺乏测试经验。说实话,他们应该担心!测试是没有商量余地的。

顶级公司——以及我工作过的所有工程团队——都遵循千层面测试策略。

他们不仅仅依靠一种类型的测试来确保代码正常工作。

任何新版本都必须经过层层考验。所有这些都是为了生产具有最少错误的可预测软件。

这就是我的意思……

基础层:单元测试

首先,您要确保您的各个函数和类按照您期望的方式运行。

单元测试是任何分层测试策略的基础。

通过编写全面的逻辑测试,您可以对自己的代码充满信心。好处是您可以在将来快速运行单元测试,以便在出现问题时立即提醒您。

这里有一些(非常愚蠢的)单元测试:

import unittest
from typing import Optional


def hello(name: Optional[str] = None) -> str:
    if name:
        return f'Hello {name}'
    return 'Hello world'


class TestHello(unittest.TestCase):
    def test_hello(self):
        self.assertEqual(hello(), 'Hello world')

    def test_hello_name(self):
        self.assertEqual(hello('John'), 'Hello John')

    def test_hello_empty_string(self):
        self.assertEqual(hello(''), 'Hello world')

他们检查我的函数是否产生了我期望的结果。

对于您编码的每个新功能,您还应该编写许多单元测试。即使是这个简单的hello()功能,我也写了 3 个单元测试!如果您正在编写更复杂的生产软件,您应该从不同角度编写大量测试。

单元测试应该快速且数量众多。每个测试应该只测试代码的单个“单元”中的代码。不要在单元测试中测试服务之间的交互或复杂的用户流。

干净、简单且易于理解。

中间层:功能/集成测试

接下来,我们为测试增加了更多的复杂性和开销。

我们测试不同服务、数据库和内部 API 之间的交互。这些测试更难编写且运行成本更高。他们要求应用程序的多个部分在测试时正在运行。

与单元测试相比,您的功能/集成测试会更少。您不应该使用它们来广泛测试单个服务的输出。相反,您应该测试服务是否按照您期望的方式进行交互。

集成测试确保两个服务可以连接并在它们之间交换数据。它可能会在交互过程中断言有关服务中间状态的数据。

这是一个集成测试:

def test_database_insert_from_orm():
    db_objects = MyModel.objects.all()
    assert len(db_objects) == 0

    response = requests.post('/api/my_model', {'name': 'New Test Model'})
    assert response.status_code == 201

    db_objects = MyModel.objects.all()
    assert len(db_objects) == 1

查看它如何与数据库交互,然后使用 API 插入对象并测试它是否存在?我们正在测试API 和数据库之间的集成。

功能测试更侧重于用户流程或业务用例。它不经常测试中间状态。相反,它关注一组给定的请求是否产生了预期的最终结果。

总之,这个中间层仍然允许您隔离应用程序的某些部分进行测试,同时忽略其他部分。但这些测试比单独的详细单元测试更广泛、更复杂。

外层:端到端测试

这是运行起来最困难和最昂贵的测试类型。但最终,它最能告诉您应用程序中真实用户将看到的内容。

对于端到端 (E2E) 测试,您运行整个应用程序。启动所有服务。让一切运行起来。

然后,您使用测试软件(如CypressSelenium)来自动化测试用户。您编写代码来告诉自动化用户采取某些操作,例如在您的应用程序周围单击、登录和执行常见的工作流程。

最后,您断言用户看到了他们应该看到的屏幕。确保页面上呈现的内容符合您的预期。

这些测试编写起来很棘手,如果应用程序的任何部分发生变化,它们可能会不稳定。尽管如此,他们还是值得为正确而付出努力。没有其他类型的测试能让您确信用户会看到正确的结果。

为什么层次很重要

单元测试非常适合细节。他们检查逻辑、实现和语法中的错误。你用单元测试覆盖了大量的基础,它们是最容易上手的。但是,它们无法告诉您复杂应用程序中不同服务之间的交互。

集成测试在确保应用程序的各个部分以您期望的方式相互通信方面非常出色。您可以在每一步断言有关应用程序状态的各种事情。但它们运行速度较慢,有时难以编写,而且不适合测试小细节或大局。

端到端测试真正着眼于全局。他们告诉你一些非常重要的事情——用户在使用应用程序时会看到什么。您可以使用一些出色的 E2E 测试来自动化大部分现有的手动测试。然而,它们更难编写且运行更慢!更重要的是,您不能断言太多关于数据库或底层代码的状态。就是用户看到的。

一起,而且只有一起,您才能全面了解您的应用程序。您可以通过编写多种不同类型的测试来获得对软件的信心。

救了我的项目

就在本周,一项 E2E 测试在我的代码中发现了单元测试和集成测试遗漏的错误!

当我发现这个错误时,我立即为它编写了一个单元测试(这样我们就可以更早地发现它,而无需运行缓慢、昂贵的 E2E 测试)。但是如果没有我们的自动化单元测试步骤来阻止它,这个错误就会进入生产!

测试是一个非常重要的话题。最好的开发人员了解测试以防止生产中出现问题的价值。此外,出色的测试可以加快新开发的速度。您可以隔离代码中的更改并快速重新运行测试,以深入了解您的更改是否破坏了其他任何东西。

这篇文章只是触及表面。想了解更多关于测试的信息?给我回信。

每日清单

我每天早上都会为软件开发人员写一些新东西。

如果你喜欢我的文章,点赞,关注,转发!

标签:代码,单元测试,应用程序,分层,objects,测试,编写,hello
From: https://blog.51cto.com/u_12409319/6116223

相关文章

  • 代码大全 阅读笔记01
    阅读了代码大全,以下是我的收获:松散耦合性:耦合性就是两个子程序之间的紧密程度。要注意耦合的规模:注意两个子程序之间的联系程度。注意两个子程序之间的联系的直接程度,越......
  • 3 月 8 日测试题解
    3月8日测试题解T1题意给你一张图\(G=(V,E)\),\(|V|=n\),\(|E|=m\),带边权、点权。你可以执行以下操作任意多次:选取一个顶点,将其自身与与其相连的边删去当你......
  • 007 springboot集合mybatis-plus,使用其中的代码生成器
    代码生成器步骤一:在pom.xml中添加相应的依赖<!--代码生成器--><dependency><groupId>com.baomidou</groupId><artifactId>......
  • 代码随想录day25|组合总和III 电话号码的字母组合
    力扣题目链接(opensnewwindow)找出所有相加之和为n的k个数的组合。组合中只允许含有1-9的正整数,并且每种组合中不存在重复的数字。分析  本题就是在[1,2,3,4......
  • chrome小恐龙作弊代码
    chrome断网后的小恐龙游戏F12打开开发者工具->console->输入如下代码,分数要多少有多少Runner.instance_.setSpeed(99999);试试瞬间满分window.tempGameOver=Runner.in......
  • Java应用【XVIII】在 Java 中使用JUnit5进行单元测试和自动化测试
    一、前言单元测试和自动化测试是现代软件开发过程中必不可少的环节,可以提高代码质量和开发效率。JUnit5是Java中流行的单元测试框架,本文将介绍如何在Java中使用JUnit5进行单......
  • 02-系统扩展、测试和监控(基于客服系统演进案例)
    一、使用Mybatis-Plus对数据访问进行扩展1、MyBatis-Plus开发模式(1)为什么用Mybatis-Plus​ Mybatis的问题:​ 通过原生SQL语句操作业务数据,自动化程度不高;通过繁杂的......
  • 重构改善既有代码的设计
    重构是在不改变外部行为的前提下,有条不紊地改善代码。MartinFowler的《重构:改善既有代码的设计》一书已经成为全球有经验的程序员手中的利器,既可用来改善既有代码的设计、......
  • Java 一行代码判断String字符串是否为纯符号
                 一行代码判断String字符串是否为纯符号 最近项目中新加的需求我感觉我的构思很好,分享给大家原理:1.将String去除前后空格2.将Str......
  • MyBatisPlus3.x代码生成器生成实体类自定义需要填充的字段
    场景 生成代码时数据库中某些公共字段比如修改人、修改时间等在生成实体时需要自动添加@TableField(fill=FieldFill.INSERT)等自动填充注解。实现在上面代码生成器的基础......