我具有使用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
...
}
注意:我正在使用Visual Studio 2019的单元测试套件,但我很好奇是否可以使用任何.NET工具
答案 0 :(得分:1)
您有两种选择:
下面显示了选项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"));
}
}
答案 1 :(得分:0)
仅出于测试目的而将内部逻辑暴露给外部世界不是最佳方法。
您应该仅针对公共api和行为进行测试。
对于性能测试,这可能很棘手,但可行。例如,如果对边缘情况执行标准Bresenham算法,则该测试方法的行为使用者将观察到什么?
执行是否需要花费500毫秒以上的时间?如果是这样,请为其编写测试,并检查边缘情况下执行所花费的时间少于500毫秒。
如果找不到这种可观察到的行为,我将不会为其编写测试,而只相信曾经编写或维护此代码的开发人员。所有开发人员都很聪明,会尽力而为。