paint-brush
稳定的软件:了解自动化测试的力量by@igorluchenkov
1,015
1,015

稳定的软件:了解自动化测试的力量

Igor Luchenkov6m2024/03/02
Read on Terminal Reader

自动化测试是一种无需花费太多时间即可测试软件的方法。测试分为三种类型:单元测试、集成测试和端到端测试。让我们深入研究每种类型并了解为什么我们需要每种类型。单元测试很快。隔离允许他们在任何时间点在本地和 CI 上运行它们,而无需启动依赖的服务/进行 API 和数据库调用。集成测试速度较慢,但它们测试应用程序各部分的连接方式。
featured image - 稳定的软件:了解自动化测试的力量
Igor Luchenkov HackerNoon profile picture

这篇文章值得您关注,如果您

  • 热衷于编写高质量的软件,并希望通过测试来增强应用程序的稳定性。


  • 厌倦了生产系统中突然出现的意外错误。


  • 需要帮助了解什么是自动化测试以及如何进行它们。

为什么我们需要自动化测试?

作为工程师,我们希望构建有用的东西,但随着我们创建的每一个新功能,我们不可避免地会增加应用程序的大小和复杂性。


随着产品的发展,手动(例如用手)测试受更改影响的每个功能变得越来越耗时。


缺乏自动化测试导致我们要么花费太多时间并降低运输速度,要么花费太少来节省速度,从而导致积压中出现新的错误以及来自 PagerDuty 的深夜电话。


相反,计算机可以通过编程重复执行相同的操作。那么,让我们将测试委托给计算机吧!


测试类型

测试金字塔


测试金字塔思想提出了三种主要类型的测试:单元测试、集成测试和端到端测试。让我们深入研究每种类型并了解为什么我们需要每种类型。

单元测试

单元是您单独测试的一小段逻辑(不依赖其他组件)。

单元测试很快。他们在几秒钟内完成。隔离允许他们在任何时间点、本地和 CI 上运行它们,而无需启动依赖的服务/进行 API 和数据库调用。


单元测试示例:接受两个数字并将它们相加的函数。我们想用不同的参数调用它并断言返回的值是正确的。


 // Function "sum" is the unit const sum = (x, y) => x + y test('sums numbers', () => { // Call the function, record the result const result = sum(1, 2); // Assert the result expect(result).toBe(3) }) test('sums numbers', () => { // Call the function, record the result const result = sum(5, 10); // Assert the result expect(result).toBe(15) })


一个更有趣的例子是 React 组件,它在 API 请求完成后呈现一些文本。我们需要模拟 API 模块以返回测试所需的值、渲染组件并断言渲染的 HTML 具有我们需要的内容。


 // "MyComponent" is the unit const MyComponent = () => { const { isLoading } = apiModule.useSomeApiCall(); return isLoading ? <div>Loading...</div> : <div>Hello world</div> } test('renders loading spinner when loading', () => { // Mocking the API module, so that it returns the value we need jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Loading...').toBeInTheDocument() }) test('renders text content when not loading', () => { // Mocking the API module jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Hello world').toBeInTheDocument() })


集成测试

当您的单元与其他单元(依赖项)交互时,我们将其称为集成。这些测试比单元测试慢,但它们测试应用程序各部分的连接方式。


集成测试示例:在数据库中创建用户的服务。这要求执行测试时数据库实例(依赖项)可用。我们将测试该服务是否可以从数据库创建和检索用户。


 import db from 'db' // We will be testing "createUser" and "getUser" const createUser = name => db.createUser(name) // creates a user const getUser = name => db.getUserOrNull(name) // retrieves a user or null test("creates and retrieves users", () => { // Try to get a user that doesn't exist, assert Null is returned const nonExistingUser = getUser("i don't exist") expect(nonExistingUser).toBe(null); // Create a user const userName = "test-user" createUser(userName); // Get the user that was just created, assert it's not Null const user = getUser(userName); expect(user).to.not.be(null) })


端到端测试

当我们测试完全部署的应用程序时,这是一个端到端测试,其中所有依赖项都可用。这些测试最好地模拟实际用户行为,并允许您捕获应用程序中所有可能的问题,但它们是最慢的测试类型。


每当您想要运行端到端测试时,您都必须配置所有基础设施并确保第三方提供商在您的环境中可用。


只想将它们用于应用程序的关键任务功能。


让我们看一个端到端的测试示例:登录流程。我们想要转到应用程序,填写登录详细信息,提交,然后查看欢迎消息。


 test('user can log in', () => { // Visit the login page page.goto('https://example.com/login'); // Fill in the login form page.fill('#username', 'john'); page.fill('#password', 'some-password'); // Click the login button page.click('#login-button'); // Assert the welcome message is visible page.assertTextVisible('Welcome, John!') })

您如何选择要编写哪种类型的测试?

请记住,端到端测试比集成慢集成测试比单元测试慢


如果您正在开发的功能是关键任务,请考虑至少编写一个端到端测试(例如在开发身份验证流程时检查登录功能如何工作)。


除了关键任务流程之外,我们还希望测试尽可能多的边缘情况和功能的各种状态。集成测试使我们能够测试应用程序的各个部分如何协同工作。


对端点和客户端组件进行集成测试是一个好主意。端点应该执行操作,产生预期的结果,并且不会抛出任何意外的错误。


客户端组件应该显示正确的内容并按照您期望的方式响应用户交互。


最后,我们什么时候应该选择单元测试?所有可以单独测试的小函数,例如对数字求和的sum 、呈现<button>标记的Button ,都是单元测试的绝佳候选者。如果您遵循测试驱动开发方法,那么单元就是完美的。


下一步是什么?

写一些测试! (但从小处开始)

  • 安装适合您的项目/语言的测试框架。每种语言都有一个流行的测试库,例如用于 JavaScript 的Jest / Vitest 、用于端到端的Cypress / Playwright (也使用 JavaScript)、用于 Java 的JUnit等。


  • 在项目中找到一个小函数并为其编写单元测试。


  • 为某些组件/服务-数据库交互编写集成测试。


  • 选择一个可以快速测试的关键场景,例如简单的登录流程,并为其编写端到端测试。


执行上述操作一次即可了解其工作原理。然后,在某些功能/错误工作期间再次执行此操作。然后分享给你的同事,让大家都写测试,节省时间,晚上睡得更好!


有用的资源: