我有一个用Bresenham算法在网格上进行光线投射的函数。我想优化特定情况下的线是正交或对角线;当然,这个逻辑不会返回/公开给用户。
是否有可能通过单元测试来检测优化边缘情况?例如,在调用函数时,请查找特定的Debug.WriteLine标记。
我刚开始进行单元测试,我可能忽略了重点(向用户公开的测试功能),但是断言我的边缘案例如预期的那样工作是非常宝贵的--特别是在积极开发优化的时候。
我想要达到的目标的例子:
public IEnumerable<Coordinate> RayCast (Coordinate source, Coordinate direction) {
if (direction.X == 0 || direction.Y == 0) {
Debug.WriteLine ("Orthogonal_Edge_Case");
//Simple iteration across 1 axis
...
yield break;
}
if (Math.Abs(direction.X) == Math.Abs(direction.Y)) {
Debug.WriteLine ("Diagonal_Edge_Case");
//Simple diagonal iteration
...
yield break;
}
//Standard Bresenham's algorithm
...
yield break;
}..。
[TestMethod]
public void TestRayCast () {
var source = new Coordinate (0,0);
var orthogonal = new Coordinate (0,1);
CoordinateUtil.RayCast (source, orthogonal);
//Check that the Orthogonal_Edge_Case marker was emitted
var diagonal = new Coordinate (1,1);
CoordinateUtil.RayCast (source, diagonal);
//Check that the Diagonal_Edge_Case marker was emitted
//Usual tests for RayCast
...
}注意:我正在使用VisualStudio2019的单元测试工具包,但我很好奇是否可以使用任何.NET工具
发布于 2019-05-19 10:30:10
你有几个选择:
下面显示了选项2的工作原理。您可能会觉得这有点过分,但是它很健壮,而且通常在大型项目中是如何完成的。还请注意,您现在正在向外部世界公开内部,只是为了帮助内部优化。如果是这样的话,这可能是不适当的。
public class CoordinateUtil
{
private readonly IEdgeCaseDetector edgeCaseDetector;
// This is the important bit where you inject an edge case detector
public CoordinateUtil(IEdgeCaseDetector edgeCaseDetector)
{
this.edgeCaseDetector = edgeCaseDetector;
}
public IEnumerable<Coordinate> RayCast(Coordinate source, Coordinate direction)
{
if (direction.X == 0 || direction.Y == 0)
{
edgeCaseDetector.Detect("Orthogonal_Edge_Case");
//Simple iteration across 1 axis
yield break;
}
if (Math.Abs(direction.X) == Math.Abs(direction.Y))
{
edgeCaseDetector.Detect("Diagonal_Edge_Case");
//Simple diagonal iteration
yield break;
}
//Standard Bresenham's algorithm
yield break;
}
}
public interface IEdgeCaseDetector
{
void Detect(string message);
}
public class EdgeCaseDetector
{
public void Detect(string message)
{
// If you wanted to you could simply save the edge cases to a public property here
// Or you might want to log them when you code runs outside of the unit test
}
}
[TestClass]
public class CoordinateUtilTests
{
[TestMethod]
public void RayCast_WhenOthogonal_DetectsEdgeCase()
{
// Arrange
var mock = new Mock<IEdgeCaseDetector>();
var coordinateUtil = new CoordinateUtil(mock.Object);
var source = new Coordinate(1, 1);
// Act
// Remember the ToArray because we need to evaluate the enumerable
// before we can check if the edge case was detected.
coordinateUtil.RayCast(source, new Coordinate(0, 0)).ToArray();
// Assert
mock.Verify(x => x.EdgeDetected("Orthogonal_Edge_Case"));
}
}发布于 2019-05-19 10:39:56
仅仅为了测试而向外部世界公开内部逻辑并不是最好的方法。
您应该只针对公共api和行为进行测试。
对于性能测试,这可能是棘手的,但可行的。例如,如果执行的边缘情况算法,测试下的方法的使用者将观察到什么行为?
执行是否需要超过500毫秒?如果是的话,为它编写测试,并检查对于边缘情况,执行所花费的时间少于500毫秒。
如果您找不到这种可观察的行为,我就不会为它编写测试,而只是信任曾经编写或维护此代码的开发人员。所有的开发人员都很聪明,并且尽了最大的努力。
https://stackoverflow.com/questions/56206494
复制相似问题