代码之家  ›  专栏  ›  技术社区  ›  THX-1138

如何测试不应该执行的代码?

  •  9
  • THX-1138  · 技术社区  · 14 年前

    只有在验证存在无效数字时(通过调用另一个方法),才能调用以下方法。我如何测试覆盖范围 throw VerifyThereAreInvalidiDigits 还有这个方法。我在找别的主意。

    public int FirstInvalidDigitPosition {
        get {
            for (int index = 0; index < this.positions.Count; ++index) {
                if (!this.positions[index].Valid) return index;
            }
            throw new InvalidOperationException("Attempt to get invalid digit position whene there are no invalid digits.");
        }
    }
    

    4 回复  |  直到 14 年前
        1
  •  22
  •   Eric Lippert    14 年前

    无法到达 在任何可能的情况下 删除 并替换为:

    Debug.Fail("This should be unreachable; please find and fix the bug that caused this to be reached.");
    

    如果代码是可访问的,那么编写一个单元测试来测试该场景。公共可访问方法的错误报告场景是完全有效的场景。你必须正确处理所有的输入,即使是错误的输入。如果正确的方法是抛出一个异常,那么测试您是否抛出了一个异常。

    更新:根据注释,实际上不可能命中错误,因此代码无法访问。但是现在调试失败也不可到达,并且它不会编译,因为编译器注意到返回值的方法具有可到达的端点。

    第一个问题实际上不应该是一个问题;当然,代码覆盖工具应该是可配置的,以忽略不可访问的纯调试代码。但这两个问题都可以通过重写循环来解决:

    public int FirstInvalidDigitPosition 
    { 
        get 
        { 
            int index = 0;
            while(true) 
            {
                Debug.Assert(index < this.positions.Length, "Attempt to get invalid digit position but there are no invalid digits!");
                if (!this.positions[index].Valid) return index; 
                index++;
            } 
        }
    }
    

    另一种方法是重新组织代码,这样您首先就不会遇到问题:

    public int? FirstInvalidDigitPosition { 
        get { 
            for (int index = 0; index < this.positions.Count; ++index) { 
                if (!this.positions[index].Valid) return index; 
            } 
            return null;
        } 
    } 
    

    现在您不需要首先限制调用者调用arereinvalidDigits;只要使随时调用此方法合法即可。这样做似乎更安全。如果你不做一些昂贵的检查来验证调用它们是否安全,那么这些方法就是脆弱的、危险的方法。

        2
  •  4
  •   Jason Williams    14 年前

    如果您认为编写代码是值得的,那么就值得对其进行单元测试。

        3
  •  4
  •   supercat    14 年前

    有时有必要编写一些不能执行的代码,只是为了安抚编译器(例如,如果一个总是抛出异常、退出应用程序等的函数是从一个应该返回值的函数调用的,编译器可能会坚持要求调用者包含一个“return 0”、“return Nothing”等语句,该语句可以从不执行。我不认为应该要求测试这样的“代码”,因为如果不严重破坏系统的其他部分,就不可能让它执行。

      register = 0
      test register for zero
      if non-zero goto dead
      register = register - 1
      test register for zero
      if non-zero goto okay1
    dead:
      shut everything down
      goto dead
    okay1:
      register = register + 1
      if non-zero goto dead
    

    我不确定在失败的情况下,人们到底会如何测试代码。本守则的目的是确保登记册如遭静电或其他损坏,或因其他原因不能运作,系统会安全关闭。不过,由于缺少一些非常奇特的设备,我不知道如何测试这样的代码。

        4
  •  3
  •   kbrimington    14 年前

    测试的部分目的是测试 应该 发生的事情 发生。

    如果你有密码 应该 从不执行,但是 能够 在正确(或错误)的条件下,您可以通过使用以下内容装饰您的测试方法来验证异常是否在正确的条件下发生(在MS的单元测试框架中):

    [ExpectedException(typeof(InvalidOperationException))]