如何使用包含其他方法的方法编写单元测试?
How to write unit test with methods that contains another methods?
好吧,我有一个使用另一种方法的方法。我有辅助方法的测试,现在我想为主要方法编写单元测试。
我认为我必须在没有看到要测试的方法的代码的情况下编写测试,我的意思是,我没有在实现中设计测试的想法,所以接下来,在 main 方法的测试中我必须测试辅助方法的功能和主要方法的功能。
例如,我有两个带汽车的车库。在车库中有汽车和我拥有的汽车数量。所以我希望能够在车库中添加一辆新车,移除一辆车并将一辆车从一个车库转移到另一个车库。所以我有这个方法:
- 一种将汽车添加到车库的方法,必须将汽车与车库相关联并更新汽车数量。这是我有新车的时候。
- 一种从车库中移除汽车的方法,将汽车与车库无关并更新汽车的数量。这是我没有车的时候,例如因为我把车卖了。
- 关于转移汽车的方法,即从第一个车库中取出汽车并将汽车添加到新车库。所以这个方法调用了add方法和remove方法。
传输方法的代码应该是这样的:
public void transferCar(garage1, garage2, car)
{
removeCar(garage1, car);
addCar(garage2, car);
}
如果我测试 removeCar 和 addCar 并且我确信它们按预期工作,为了测试传输,我必须测试 addCar 的所有情况以及 removeCar 的所有情况?因为如果不知道transferCar的实现,就不知道这个方法有没有使用removeCar和addCar,所以不知道这个方法有没有达到预期的效果。
换句话说,当我测试transferCar时,测试必须覆盖100%的removeCar代码,100%的addCar代码和100%的transferCar方法代码,或者确保我调用方法 removeCar 一次并在 transferCar 中调用 addCar 并且它按预期工作就足够了,尽管 removecar 和 addCar 没有被 100% 覆盖?
因为如果我必须测试 removeCar 和 addCar 的所有情况,我会做两次相同的测试。所以我重构了代码,因为 removeCar 和 addCar 我在很多地方都使用它,但是在我的测试代码中我有很多次相同的测试。
这是一个非常单一的例子,但是如果我有一个方法使用了很少的方法而这个其他方法使用了其他方法,并且主要方法应该覆盖所有方法的所有代码,那将是一个非常长的测试,还有很多工作。
总之,当我测试一个方法时,我已经覆盖了这个方法的 100% 的代码和这个方法使用的方法的 100% 的代码,或者只是为了确保主要方法的工作正如预期的那样,每个辅助方法调用一次?
谢谢。
TDD 并不意味着您需要对实现细节有零知识,它是测试优先的编程概念。单元测试是白盒测试,对于这个测试,应该确切地知道 class 实现是什么。黑盒测试可能不需要了解实现细节。
严格来说,单元测试应该只测试 class 的 public 接口,看看我们是否为 class 提供了 100% 的覆盖率(包括其所有私有和受保护的代码)。
一个函数的覆盖率是为了查看该特定函数测试了多少行代码以及验证了多少分支(if-else,switch..)。
对于您的情况,我会为转移汽车编写一个简单的测试用例,并断言检查汽车是否从车库 1 转移到车库 2。这将 100% 覆盖 transferCar()。然后,您可以编写广泛的多个测试用例,以实现 addCar() 和 removeCar() 的良好覆盖,我希望它们是 public 方法。如果他们是私人的,那么检查 here
如果您想跳过调用真正的实现,那么模拟是可行的方法,但这取决于您实现代码的方式。如果被测函数(可以说是主函数)调用它自己的实例方法然后模拟被调用的函数很棘手。
好吧,我有一个使用另一种方法的方法。我有辅助方法的测试,现在我想为主要方法编写单元测试。
我认为我必须在没有看到要测试的方法的代码的情况下编写测试,我的意思是,我没有在实现中设计测试的想法,所以接下来,在 main 方法的测试中我必须测试辅助方法的功能和主要方法的功能。
例如,我有两个带汽车的车库。在车库中有汽车和我拥有的汽车数量。所以我希望能够在车库中添加一辆新车,移除一辆车并将一辆车从一个车库转移到另一个车库。所以我有这个方法:
- 一种将汽车添加到车库的方法,必须将汽车与车库相关联并更新汽车数量。这是我有新车的时候。
- 一种从车库中移除汽车的方法,将汽车与车库无关并更新汽车的数量。这是我没有车的时候,例如因为我把车卖了。
- 关于转移汽车的方法,即从第一个车库中取出汽车并将汽车添加到新车库。所以这个方法调用了add方法和remove方法。
传输方法的代码应该是这样的:
public void transferCar(garage1, garage2, car)
{
removeCar(garage1, car);
addCar(garage2, car);
}
如果我测试 removeCar 和 addCar 并且我确信它们按预期工作,为了测试传输,我必须测试 addCar 的所有情况以及 removeCar 的所有情况?因为如果不知道transferCar的实现,就不知道这个方法有没有使用removeCar和addCar,所以不知道这个方法有没有达到预期的效果。
换句话说,当我测试transferCar时,测试必须覆盖100%的removeCar代码,100%的addCar代码和100%的transferCar方法代码,或者确保我调用方法 removeCar 一次并在 transferCar 中调用 addCar 并且它按预期工作就足够了,尽管 removecar 和 addCar 没有被 100% 覆盖?
因为如果我必须测试 removeCar 和 addCar 的所有情况,我会做两次相同的测试。所以我重构了代码,因为 removeCar 和 addCar 我在很多地方都使用它,但是在我的测试代码中我有很多次相同的测试。
这是一个非常单一的例子,但是如果我有一个方法使用了很少的方法而这个其他方法使用了其他方法,并且主要方法应该覆盖所有方法的所有代码,那将是一个非常长的测试,还有很多工作。
总之,当我测试一个方法时,我已经覆盖了这个方法的 100% 的代码和这个方法使用的方法的 100% 的代码,或者只是为了确保主要方法的工作正如预期的那样,每个辅助方法调用一次?
谢谢。
TDD 并不意味着您需要对实现细节有零知识,它是测试优先的编程概念。单元测试是白盒测试,对于这个测试,应该确切地知道 class 实现是什么。黑盒测试可能不需要了解实现细节。
严格来说,单元测试应该只测试 class 的 public 接口,看看我们是否为 class 提供了 100% 的覆盖率(包括其所有私有和受保护的代码)。
一个函数的覆盖率是为了查看该特定函数测试了多少行代码以及验证了多少分支(if-else,switch..)。
对于您的情况,我会为转移汽车编写一个简单的测试用例,并断言检查汽车是否从车库 1 转移到车库 2。这将 100% 覆盖 transferCar()。然后,您可以编写广泛的多个测试用例,以实现 addCar() 和 removeCar() 的良好覆盖,我希望它们是 public 方法。如果他们是私人的,那么检查 here
如果您想跳过调用真正的实现,那么模拟是可行的方法,但这取决于您实现代码的方式。如果被测函数(可以说是主函数)调用它自己的实例方法然后模拟被调用的函数很棘手。