JavaScript/TypeScript中TDD的最佳实践



问题

  • 访问模块中所有JavaScript/TypeScript函数进行单元测试的正确/可接受的方式是什么
  • 有没有一个(好的)理由让我不应该只导出我的所有函数

上下文

请原谅我的无知;我职业生涯的大部分时间都在使用测试驱动开发(TDD)方法编写Python代码。现在,我发现自己正在学习ReactJS/TypeScript,并弄清楚如何实现单元测试,但我很快发现,只有导出函数才能访问它们。正如你们大多数人所知,Python是非常宽容的;实际上没有隐私的概念,所以这只是导入模块并尊重您可以访问的内容的问题。但JavaScript只导入已明确导出的模块的功能,因此提供了一个适度的障碍。

有人告诉我,导出我的所有函数进行测试不是一个好主意,但我不知道有其他方法可以真正测试它们。

示例

有人告诉我;"正确/更好":

示例1.js:

const func1 = () => {
//code that does stuff
return "stuff";
};
const func2 = () => {
//code that does other stuff
return "otherStuff";
};
export { func1 };

Sample1.test.js:

// executed via Jest framework
import * as sample from "./Sample1.js"
describe("Unit Tests for Sample1", () => {
test("Unit Test - func1", () => {
// code that tests stuff
};
test("Unit Test - func2", () => {
// can't test func2 because it's not exported
};
};

我正在做的是能够测试所有功能:

示例2.js:

const func1 = () => {
//code that does stuff
return "stuff";
};
const func2 = () => {
//code that does other stuff
return "otherStuff";
};
export { func1, func2 };

Sample2.test.js:

// executed via Jest framework
import * as sample from "./Sample2.js"
describe("Unit Tests for Sample2", () => {
test("Unit Test - func1", () => {
// code that tests stuff
};
test("Unit Test - func2", () => {
// code that tests other stuff because it's exported
};
};

记录在案

我在互联网和Stack Overflow上专门查找了标准和最佳实践,但我没有发现太多能回答这个特定问题的内容。我发现的最接近的问题是这个SO问题,但这并不是我真正想要的。

如果您在测试系统(SUT)之前编写测试,从而真正进行测试驱动开发(TDD),那么您可以将测试视为SUT的可执行规范。(如果这对你来说已经很明显了,我很抱歉,但Stack Overflow上的许多人将TDD一词与单元测试互换使用,并说他们做TDD,即使他们在SUT之后写测试。)

因此,测试描述了SUT的API。在具有访问修饰符和/或显式导出功能的语言中,您需要使SUT可用于测试。在JavaScript中,这意味着您必须导出要测试的API。在其他带有访问修饰符的语言中,这也意味着必须提供SUT APIpublic可用性(例如Java和C#)。

如果您正在开发一个库,这也将与客户端代码可用的API相一致。事实上,测试是SUT的第一个(或最早的)客户端。

一旦测试到位,它们就充当SUT的回归测试套件。因此,如果测试失败,则表明导出的API的某些部分已损坏。这也意味着该部分将被使用它的客户端代码破坏

那么,是否应该导出所有方法?

不一定。您可能希望将某些方法隐藏为实现详细信息。这可能有多种充分的理由。也许您不确定助手方法的API是否健壮,并且您希望保留在不破坏客户端代码的情况下更改它的能力。也许helper方法的封装性较差。

只要在TDD过程中创建了这样的辅助方法,即使它们本身没有导出,它们仍然会被测试过渡性地覆盖。

最新更新