首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >边缘情况发生的单元测试检查

边缘情况发生的单元测试检查
EN

Stack Overflow用户
提问于 2019-05-19 09:31:24
回答 2查看 349关注 0票数 1

我有一个用Bresenham算法在网格上进行光线投射的函数。我想优化特定情况下的线是正交或对角线;当然,这个逻辑不会返回/公开给用户。

是否有可能通过单元测试来检测优化边缘情况?例如,在调用函数时,请查找特定的Debug.WriteLine标记。

我刚开始进行单元测试,我可能忽略了重点(向用户公开的测试功能),但是断言我的边缘案例如预期的那样工作是非常宝贵的--特别是在积极开发优化的时候。

我想要达到的目标的例子:

代码语言:javascript
复制
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;
}

..。

代码语言:javascript
复制
[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工具

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-19 10:30:10

你有几个选择:

  1. 使用CoordinateUtil中的属性保持某种状态,这将允许您检查检测到的最后边缘是什么。然而,这将破坏命令查询责任分离模式
  2. 注入一个边缘案例检测器(您可以很容易地模拟框架)。下面的示例使用莫克
  3. 注入一个ILogger,它将允许您记录一些时间信息以及其他事情(非常类似于option2,但使用略有不同的设置)。

下面显示了选项2的工作原理。您可能会觉得这有点过分,但是它很健壮,而且通常在大型项目中是如何完成的。还请注意,您现在正在向外部世界公开内部,只是为了帮助内部优化。如果是这样的话,这可能是不适当的。

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2019-05-19 10:39:56

仅仅为了测试而向外部世界公开内部逻辑并不是最好的方法。

您应该只针对公共api和行为进行测试。

对于性能测试,这可能是棘手的,但可行的。例如,如果执行的边缘情况算法,测试下的方法的使用者将观察到什么行为?

执行是否需要超过500毫秒?如果是的话,为它编写测试,并检查对于边缘情况,执行所花费的时间少于500毫秒。

如果您找不到这种可观察的行为,我就不会为它编写测试,而只是信任曾经编写或维护此代码的开发人员。所有的开发人员都很聪明,并且尽了最大的努力。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56206494

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档