惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
F
Fortinet All Blogs
B
Blog
GbyAI
GbyAI
P
Proofpoint News Feed
量子位
The Register - Security
The Register - Security
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
B
Blog RSS Feed
WordPress大学
WordPress大学
Recorded Future
Recorded Future
Recent Announcements
Recent Announcements
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Secure Thoughts
雷峰网
雷峰网
Stack Overflow Blog
Stack Overflow Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Webroot Blog
Webroot Blog
AWS News Blog
AWS News Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The GitHub Blog
The GitHub Blog
爱范儿
爱范儿
O
OpenAI News
月光博客
月光博客
H
Hacker News: Front Page
S
Security Affairs
W
WeLiveSecurity
The Hacker News
The Hacker News
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Help Net Security
Help Net Security
MongoDB | Blog
MongoDB | Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
D
Docker
T
The Blog of Author Tim Ferriss
Spread Privacy
Spread Privacy
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
S
Securelist
Microsoft Azure Blog
Microsoft Azure Blog
TaoSecurity Blog
TaoSecurity Blog
T
Threat Research - Cisco Blogs
M
MIT News - Artificial intelligence
A
About on SuperTechFans

szhshp 的第三边境研究所

假设, AI 把我代替的那一刻真的到来 | szhshp 的第三边境研究所 小傻瓜都能懂的 AstrBot QQ 机器人集成 MCP 功能实战指南 | szhshp 的第三边境研究所 《智人之上: 从石器时代到 AI 时代的信息网络简史》阅读笔记 | szhshp 的第三边境研究所 iPadOS 26 无法设置空间场景图片壁纸的解决方法 | szhshp 的第三边境研究所 《一路云海》(终) | szhshp 的第三边境研究所 《一路云海》(四): 如何不按套路旅行 | szhshp 的第三边境研究所 《一路云海》(三): In Ya Mellow Tone | szhshp 的第三边境研究所 《一路云海》(二): 关西世博参观纪实 | szhshp 的第三边境研究所 《一路云海》(一): 新的征程 | szhshp 的第三边境研究所 2025 大阪世博会 [ 3 天前-先到先得 ] 阶段 场馆预约必中独家攻略 | szhshp 的第三边境研究所 Hackathon 随想 | szhshp 的第三边境研究所 一杯双皮奶 | szhshp 的第三边境研究所 Armbian + CasaOS + NAS 配置指南 | szhshp 的第三边境研究所 Docker 构建镜像报错: error getting credentials - err: exit status 1, out: `` | szhshp 的第三边境研究所 Disqus RIP! 论过高的维护成本如何治疗固执的坏习惯 | szhshp 的第三边境研究所 炸弹猫桌游变体规则 | szhshp 的第三边境研究所 《小岛经济学》阅读笔记 | szhshp 的第三边境研究所 《金钱心理学》阅读笔记 | szhshp 的第三边境研究所 为知笔记 RIP: 迁移剩余的笔记 | szhshp 的第三边境研究所 2025 博客第十年展望 - 再见我的过去 | szhshp 的第三边境研究所 我在独立游戏里面致敬的作品 | szhshp 的第三边境研究所 《How to make thing faster》阅读笔记 | szhshp 的第三边境研究所 《The Art of Clean Code》阅读笔记 | szhshp 的第三边境研究所 《Clean Architecture: A Craftsman Guide to Software Structure and Design》阅读笔记 | szhshp 的第三边境研究所 《How AI Works》阅读笔记 | szhshp 的第三边境研究所 游戏策划废案 - Project Uranus | szhshp 的第三边境研究所 游戏策划废案 - Project X | szhshp 的第三边境研究所 人生第一款独立游戏开发复盘 | szhshp 的第三边境研究所 Trap of Life | szhshp 的第三边境研究所 如果我用手搓了个暗物质雏形 | szhshp 的第三边境研究所 《Rust Programming Language》- EX - Cheatsheet | szhshp 的第三边境研究所 新的播放器上线了 | szhshp 的第三边境研究所 Cypress - End-to-End Testing: OKTA Authentication with MFA | szhshp 的第三边境研究所 VSC x VIM - 反正多学几个快捷键没有坏处 | szhshp 的第三边境研究所 两小时 Docker 速成 - Getting Started | szhshp 的第三边境研究所 《The Joy of Javascript》- 5 - Data | szhshp 的第三边境研究所 《The Joy of Javascript》- 4 - Meta Programming | szhshp 的第三边境研究所 《The Joy of Javascript》- 3 - ADT(Algebraic Data Type) | szhshp 的第三边境研究所 《The Joy of Javascript》- 2 - Functor/Monad | szhshp 的第三边境研究所 《The Joy of Javascript》- 1 - Object/Function | szhshp 的第三边境研究所 EvalError: Possible side-effect in debug-evaluate | szhshp 的第三边境研究所 前端 QA 工具链指南 - husky,commitlint,commitizen,eslint,typescript,express | szhshp 的第三边境研究所 效率工具 & 软件推荐 | szhshp 的第三边境研究所 站点开源 Project Titan | szhshp 的第三边境研究所 cmd/powershell-命令速查-Cheatsheet | szhshp 的第三边境研究所 Git-命令速查与相关问题解决-Cheatsheet & Troubleshooting | szhshp 的第三边境研究所 Tailwind.css not included in NextJS Production | szhshp 的第三边境研究所 Github GraphQL API - Data Integration | szhshp 的第三边境研究所 尝试 Windows Terminal + z.lua | szhshp 的第三边境研究所 StrokePlus.net - Powerful Hotkey Boost | szhshp 的第三边境研究所 优雅地 Hack 一台黑苹果 | szhshp 的第三边境研究所 一杯关东煮 | szhshp 的第三边境研究所 Gitee x PicGo 管理图床 | szhshp 的第三边境研究所 Create Your Own Redux (Typescript) | szhshp 的第三边境研究所 Getting Started: Ionic + Capacitor + React + Typescript + Android | szhshp 的第三边境研究所 GraphQL: File Upload & Troubleshooting | szhshp 的第三边境研究所 吉祥航空随心飞刷票工具循环查票工具 | szhshp 的第三边境研究所 NVM Windows Portable Installation | szhshp 的第三边境研究所 NextJS x Typescript - Integration & Troubleshooting | szhshp 的第三边境研究所 全站点升级 - Project Titan | szhshp 的第三边境研究所 AWS-EC2-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 Workbox-Getting Started | szhshp 的第三边境研究所 《时间简史》阅读笔记 | szhshp 的第三边境研究所 《时间的秩序》阅读笔记 | szhshp 的第三边境研究所 ESLint-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 站点索引 | szhshp 的第三边境研究所 个人知识库搭建 - Hexo 实现 Github/Coding 持续集成 | szhshp 的第三边境研究所 BMOB-常见问题解决-Troubleshooting | szhshp 的第三边境研究所 React + Typescript: 开启 HMR/Hot Loader | szhshp 的第三边境研究所 Yarn & NPM | szhshp 的第三边境研究所 ESLint: Typescript + React + TSX 集成 | szhshp 的第三边境研究所 《10101》EP15:过年 2020 | szhshp 的第三边境研究所 Cmder-Usage | szhshp 的第三边境研究所 Redux-DOM not refreshed | szhshp 的第三边境研究所 React Semantic UI-CheatSheet | szhshp 的第三边境研究所 Typescript: Getting Started | szhshp 的第三边境研究所 Flutter-Getting Started | szhshp 的第三边境研究所 Typescript: Access window object with type check | szhshp 的第三边境研究所 VSC Extension Development-Create A Code Formatter Extension | szhshp 的第三边境研究所 OneNote Extension-Main API | szhshp 的第三边境研究所 TortoiseGit Win10 Icon not showing correctly | szhshp 的第三边境研究所 Mongoose: aggregate() 方法实现聚合函数 | szhshp 的第三边境研究所 React In Depth - React 源码解析 - render() & Fiber | szhshp 的第三边境研究所 MongoDB x Mongoose: 实现类似 Join 的功能 | szhshp 的第三边境研究所 Disqus 评论框改造工程-实现 Disqus 代理的 Serverless 服务 | szhshp 的第三边境研究所 GUI, CLI, Terminal, Shell, TTY, Console, Bash | szhshp 的第三边境研究所 Jest Async Best Practise: No Nested Async | szhshp 的第三边境研究所 关系型数据库与非关系型数据库优缺点分析 | szhshp 的第三边境研究所 New Edge & Chromium Error - Package is invalid: 'CRX_VERSION_NUMBER_INVALID' | szhshp 的第三边境研究所 选择 GraphQL 的 N 个理由 | szhshp 的第三边境研究所 StrokePlus - 鼠标手势神器的代码编写技巧 | szhshp 的第三边境研究所 嗨,好久不见 | szhshp 的第三边境研究所 Vue + ElementUI 集成 Vue Router | szhshp 的第三边境研究所 IE8 - Unknown Runtime Error Using innerHTML & Ajax | szhshp 的第三边境研究所 React: Handling Events | szhshp 的第三边境研究所 React-Navigation Integration with Redux | szhshp 的第三边境研究所 React: States is tricky | szhshp 的第三边境研究所 《10101》EP14:小剧场 | szhshp 的第三边境研究所 ColdFusion - Basic - arguments in cffunction | szhshp 的第三边境研究所 ColdFusion - Basic - cfset | szhshp 的第三边境研究所
Web-Automation Testing | szhshp 的第三边境研究所
2022-06-25 · via szhshp 的第三边境研究所

Meta

目录

Web - Automation Testing

Hints

  • Make your test FAIL AT BEGINNING. Otherwise it may not work properly as you thought.
  • (For UI Test) Test the feature like a user instead of a developer. We don’t need to test the implementation details.
  • Only write test for current layer, do not drill down, we can create another test case to cover deeper layers/components
  • Do not include more dependencies if you can do it with Vanilla JS + Jest + Mock
  • All unit tests should be able to run WITHOUT NETWORK. Disable your network and run it to make sure no request sent.
    • You can print log in HTTP module to check if any request are sent
  • Run unit tests in PR pipeline and run integration tests (+E2E tests) on deploy pipeline.
  • Modularization: Input and output should be clear for a module, which could be more testing-friendly
  • Try to use hardcoded string on testing, if the constant variables changed, the test case will find the change and notify you
  • Try to write new feature together with test case (or follow the TDD pattern from start of your project)

Best Practice

Commands

PurposeCommandComment
Run single test filenpx jest src\folder\yourComponent1.test.jsFind the file first
Run single test case by case name (Recommended)npx jest -t='keyword' --watchProvide a keyword and run test with keyword

Debug

  • screen.debug():
    • Prints the HTML to CLI, usually it will only print part of the content, you can set the env var to show more: DEBUG_PRINT_LIMIT=20000. Or you can set the env var in test cases: process.env.DEBUG_PRINT_LIMIT = 20000;
  • screen.logTestingPlaygroundURL():
    • Generate an URL powered by testing playground, you can open the url within browser.
    • Note that theme provider may not work
  • it.only/describe.only to run only single test case/suite

UI Testing

https://kentcdodds.com/blog/common-mistakes-with-react-testing-library

Wait For Appearance

Usually used for feature with animation or loading indicator.

  • WaitFor must return an boolean
  • Remember to add await before WaitFor, otherwise it may not work
  • Animation can be tests with waitFor + timeout
RTL
  1. Testing Library Query Priority
  2. Types of Queries
  3. Appearance and Disappearance
  4. Use title case for test ID (data-testid="This-Is-A-Test-Id")
JEST
  1. jest.mock will be hoist to the top so mocking is used for whole file. We can use jest.spyOn to mock the implementation on each test case.
  2. jest.mock will ignore the original behaviour but jest.spyOn won’t. We can use both to check if certain function have been called.
  3. Put spyOn on the top of each test case, especially before the render()
  4. When create new test:
    • Check if we can mock the input or implementation
    • Is this module too big? Can we split it into smaller modules and write test for each?

Dev - Jest Cheatsheet

Manual Mocks

https://jestjs.io/docs/manual-mocks#mocking-user-modules

  • Mocking user modules:
    1. __mocks__/module.js subdirectory immediately adjacent to the module
    2. Add jest.mock('./moduleName') at top of the test
  • Mocking node modules:
    1. __mocks__/module.js at ROOT path
    2. NO need to call jest.mock explicitly, it will be mocked automatically

Partially Mock

https://jestjs.io/docs/mock-functions#mocking-partials

SpyOn would be more convenient to do the mock.

Spy and Mock

/* import all */
import * as RequestUtils from 'src/utils';

/* DO NOT DO THIS */
// import RequestUtils from 'src/utils'; 

jest.spyOn(RequestUtils, 'requestUtil').mockImplementationOnce(() => {
  return Promise.reject('mocked error');
})

Another example:

import { createChannel, createClient } from "nice-grpc";
const foo = { createChannel, createClient };

jest.spyOn(foo, "createClient").mockReturnValue({});
jest.spyOn(foo, "createChannel").mockReturnValue({});

React Testing Library

Basic Test
import React from "react";
import { render } from "@testing-library/react";
import { FixedButton } from "src/components/button";

describe("Button Component", () => {
  it("should renders correctly", () => {
    const { container } = render(<FixedButton />);
    expect(container).not.toBeUndefined();
    expect(container).toMatchSnapshot();
  });
});
Nested Query
const title = await findByRole('heading', { name: /search results/i });
expect(await title).toBeVisible();
within(title).findByRole('progressbar');

(?) Mock a React Hook

import { useData } from "src/hooks";

/* required to set mockdata into a variable with name pattern "mock*" */
const mockData = {
  data: 123456
}

jest.mock("src/hooks", () => ({
  useData: jest.fn(),
}));

describe('Test for the mock data', () => {
  it('should return mocked data', () => {
    (useData as any).mockReturnValue(mockData);
    /* assertions */
  })

})

Mock Component

Named Export
jest.mock(
  "src/NativeCommentBox",
  () => ({
    /* make sure for the correct export name */
    NativeCommentContainer: () => (
      <span data-testid={nativeCommentContainerTestId}>children</span>
    ),
  })
);
Default Export
jest.mock("react-markdown", () => ({
  default: () => <>children</>,
}));

Troubleshoot

Test case are skiped

Delete .only()

State are shared between tests

Similar Scenario:

  • Testing are fail on second test.
  • Testing fails randomly

Potentially you are import the component with providers.

Try to write a renderer function with isolated providers.

export const renderWithState = (
  component,
  { initialState, ...renderOptions } = {}
) => {
  const initialStore = getInitialStore(initialState);
  const Wrapper = ({ children }) => {
    return (
      <StoreProvider store={initialStore}>
        <OtherProvider>
          {children}
        </OtherProvider>
      </StoreProvider>
    );
  };

  return render(component, { wrapper: Wrapper, ...renderOptions });
};
Important Note: Custom renderer with Providers
const { container } = renderer(
  <MyComponent />
);

expect(container).not.toBeNull(); /* This works */
const { container, getByRole } = renderWithState( /* renderWithState may render 'MyComponent' with Providers  */
  <MyComponent />
);

/* Potentially this will be always true because we have wrap 'MyComponent' with Providers */
expect(container).not.toBeNull(); 


/* Try to do other assertions on the elements within container instead of just check container */

Jest Hints

jest.mock() hoists mocks to the top of your module’s scope

TypeError: Expected container to be an Element, a Document or a DocumentFragment but got string

import {
  fireEvent, 
  queryByRole,   /* DO NOT DO THIS */
  render, 
  waitFor
} from '@testing-library/react';

const {
  container, queryByRole  /* DO THIS */
} = render(<App />);

data-testid shows in React Dev Tools but not in Element Tab

Prevent to put the data-testid to custom components.

Otherwise we need to pass the data-testid to children components explicitly. ß

const Panel = ({
  attr1,
  attr2 
  ...rest
}) => {
  return (
    <PanelHeader
      attr1={attr1}
      attr2={attr2}
      {...rest}
    >
  )
}

When testing, code that causes React state updates should be wrapped into act(…)

https://davidwcai.medium.com/react-testing-library-and-the-not-wrapped-in-act-errors-491a5629193b

Warning: You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one.

This is usually same request happend in same period.

Check if you forget to add ‘await’ before find* or waitFor

Jest.SpyOn.Mock doesn’t work

SpyOn and should write before the render.

References