您应该在每个 `test()/it()` 块中还是全局渲染组件/select 元素?
Should you render components / select elements in each `test()/it()` block or globally?
在 react-testing-library
中,您必须先渲染 React 组件,然后再对其元素执行一些测试。
对于同一个组件的多个测试,你应该避免
多次渲染组件?或者你必须在每个
test()/it()
块?
你应该 select 每个 test()/it()
块中的组件元素(例如按钮),还是应该抬起 selection,并且 select只有一次?
对测试的执行时间有影响吗?
其中一种方法是最好的吗practice/antipattern?
为什么最后一个例子失败了?
对于基本组件我有以下测试方法:
function MyComponent() {
return (
<>
<button disabled>test</button>
<button disabled>another button</button>
</>
);
}
例如
describe("MyComponent", () => {
it("renders", async () => {
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
expect(button).toBeInTheDocument();
});
it("is disabled", async () => {
// repetetive render and select, should be avoided or adopted?
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
expect(button).toBeDisabled();
});
});
对比
describe("MyComponent", () => {
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
it("renders", async () => {
expect(button).toBeInTheDocument();
});
it("is disabled", async () => {
expect(button).toBeDisabled();
});
});
我希望第二种方法的执行时间更快,因为组件只需要渲染一次,但我不知道如何衡量它以及它是否是反模式?
虽然它似乎更多 DRY,但如果我添加另一个 toBeInTheDocument
检查,它会失败。
为什么会这样?
describe("MyComponent", () => {
const { getByRole } = render(<MyComponent />);
const button = screen.getByRole("button", { name: /test/i });
const button2 = screen.getByRole("button", { name: /another button/i });
it("renders", async () => {
expect(button).toBeInTheDocument(); //ok
});
it("is disabled", async () => {
expect(button).toBeDisabled(); // ok
});
it("renders second button", async () => {
expect(button2).toBeInTheDocument(); // fails: element could not be found in the document
});
});
所以这个方法好像比较容易出错!?
每个测试都应该尽可能地原子化,这意味着它不应该使用其他测试也在使用的任何东西,并且应该 运行 具有新的状态。因此,将其与您的示例相关联,第一个将是正确的模式。
当您的测试套件包含单元测试之间的可共享状态时,例如对象或环境变量,测试套件很容易出错。原因是;如果其中一个单元测试碰巧改变了其中一个共享对象;所有其他单元测试也会受此影响,导致它们表现出不需要的行为。这可能会导致测试失败 - 代码在技术上是正确的,甚至为未来的开发人员设置地雷,其中添加正确的新测试仍然会导致失败,因此在弄清楚为什么会发生这种情况时造成严重的头痛。
此规则的唯一例外是不可变原始变量(例如 string
、number
、boolean
使用 const
关键字),因为测试不会能够改变它们,它们对于存储可重用的 ID、文本等很有用。
当然,重复每个单元测试的设置会使它们变得非常笨重,这就是为什么 jest
提供 beforeEach
、beforeAll
、afterEach
和 afterAll
函数提取重复逻辑。但是,这会打开共享状态的漏洞,因此请务必小心并确保在开始任何测试之前刷新所有状态。 Ref.
关于最后一个示例中最后一个单元测试为何失败的问题 - 看来您正在使用 getByRole
来查找按钮文本。您应该改用 getByText
。 getByRole
与您似乎没有使用的 role
属性(例如 <button role="test">test</button>
)一起使用。
在 react-testing-library
中,您必须先渲染 React 组件,然后再对其元素执行一些测试。
对于同一个组件的多个测试,你应该避免 多次渲染组件?或者你必须在每个
test()/it()
块?你应该 select 每个
test()/it()
块中的组件元素(例如按钮),还是应该抬起 selection,并且 select只有一次?对测试的执行时间有影响吗?
其中一种方法是最好的吗practice/antipattern?
为什么最后一个例子失败了?
对于基本组件我有以下测试方法:
function MyComponent() {
return (
<>
<button disabled>test</button>
<button disabled>another button</button>
</>
);
}
例如
describe("MyComponent", () => {
it("renders", async () => {
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
expect(button).toBeInTheDocument();
});
it("is disabled", async () => {
// repetetive render and select, should be avoided or adopted?
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
expect(button).toBeDisabled();
});
});
对比
describe("MyComponent", () => {
const { getByRole } = render(<MyComponent />);
const button = getByRole("button", { name: /test/i });
it("renders", async () => {
expect(button).toBeInTheDocument();
});
it("is disabled", async () => {
expect(button).toBeDisabled();
});
});
我希望第二种方法的执行时间更快,因为组件只需要渲染一次,但我不知道如何衡量它以及它是否是反模式?
虽然它似乎更多 DRY,但如果我添加另一个 toBeInTheDocument
检查,它会失败。
为什么会这样?
describe("MyComponent", () => {
const { getByRole } = render(<MyComponent />);
const button = screen.getByRole("button", { name: /test/i });
const button2 = screen.getByRole("button", { name: /another button/i });
it("renders", async () => {
expect(button).toBeInTheDocument(); //ok
});
it("is disabled", async () => {
expect(button).toBeDisabled(); // ok
});
it("renders second button", async () => {
expect(button2).toBeInTheDocument(); // fails: element could not be found in the document
});
});
所以这个方法好像比较容易出错!?
每个测试都应该尽可能地原子化,这意味着它不应该使用其他测试也在使用的任何东西,并且应该 运行 具有新的状态。因此,将其与您的示例相关联,第一个将是正确的模式。
当您的测试套件包含单元测试之间的可共享状态时,例如对象或环境变量,测试套件很容易出错。原因是;如果其中一个单元测试碰巧改变了其中一个共享对象;所有其他单元测试也会受此影响,导致它们表现出不需要的行为。这可能会导致测试失败 - 代码在技术上是正确的,甚至为未来的开发人员设置地雷,其中添加正确的新测试仍然会导致失败,因此在弄清楚为什么会发生这种情况时造成严重的头痛。
此规则的唯一例外是不可变原始变量(例如 string
、number
、boolean
使用 const
关键字),因为测试不会能够改变它们,它们对于存储可重用的 ID、文本等很有用。
当然,重复每个单元测试的设置会使它们变得非常笨重,这就是为什么 jest
提供 beforeEach
、beforeAll
、afterEach
和 afterAll
函数提取重复逻辑。但是,这会打开共享状态的漏洞,因此请务必小心并确保在开始任何测试之前刷新所有状态。 Ref.
关于最后一个示例中最后一个单元测试为何失败的问题 - 看来您正在使用 getByRole
来查找按钮文本。您应该改用 getByText
。 getByRole
与您似乎没有使用的 role
属性(例如 <button role="test">test</button>
)一起使用。