Pex 检测能否导致代码改变其效果?

发布于 2024-10-25 23:40:12 字数 1967 浏览 8 评论 0原文

我有一个简单的 JSON 词法分析器类;它需要一个字符串并生成一个IJSONValueIJSONValue 有一个 ToJSONString 方法,可返回有效的 JSON 字符串。

当然,其代码非常复杂,有很多分支;这就是为什么我认为这将是测试 Pex 能力的完美场所。我创建了以下测试:

[TestClass]
[PexClass]
public partial class JSONTests {
    [PexGenericArguments(typeof(JSONArray))]
    [PexGenericArguments(typeof(JSONBoolean))]
    [PexGenericArguments(typeof(JSONNull))]
    [PexGenericArguments(typeof(JSONNumber))]
    [PexGenericArguments(typeof(JSONObject))]
    [PexGenericArguments(typeof(JSONString))]
    [PexMethod]
    public void TestLexer<T>([PexAssumeNotNull] T value) where T : IJSONValue {
        string json = value.ToJSONString();
        IJSONValue result = new JSONLexer().GetValue(json);

        PexAssert.AreEqual(value, result);
    }
}

在此运行 Pex 时,我发现了一些与空处理无​​关的问题,我已修复这些问题。然而,我也得到了很多报告没有意义的异常的方法。它们看起来像这样:

[TestMethod]
[PexGeneratedBy(typeof(JSONTests))]
[PexRaisedException(typeof(JSONException))]
public void TestLexerThrowsJSONException78() {
    JSONBoolean s0 = new JSONBoolean(true);
    this.TestLexer<JSONBoolean>(s0);
}

然而,这与我知道有效的测试之一非常相似。我在调试器中和调试器外运行了它,在这两种情况下测试都通过了。最令人难以置信的是,异常文本实际上是有意义的;如果 Constant 正则表达式与字符串 "false" 不匹配,则会报告该文本。对于其他正则表达式不匹配,我得到类似的异常,这是没有意义的。

为什么 Pex 认为这会引发异常?检测是否以奇怪的方式与 ThreadLocal 或 Regex 混淆?这就是我的正则表达式持有类的样子(为了简洁起见,对正则表达式进行了编辑)。

private static class Regexes {
    private static RegexOptions Options = RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace;
    public static ThreadLocal<Regex> String = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
    public static ThreadLocal<Regex> Number = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
    public static ThreadLocal<Regex> Constant = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
}

I've got a simple JSON lexer class; it takes a string and generates an IJSONValue; the IJSONValue has a ToJSONString method that returns a valid JSON string.

The code for that, of course, is quite complicated with plenty of branches; that's why I thought this would be the perfect place to test Pex's abilities. I created the following test:

[TestClass]
[PexClass]
public partial class JSONTests {
    [PexGenericArguments(typeof(JSONArray))]
    [PexGenericArguments(typeof(JSONBoolean))]
    [PexGenericArguments(typeof(JSONNull))]
    [PexGenericArguments(typeof(JSONNumber))]
    [PexGenericArguments(typeof(JSONObject))]
    [PexGenericArguments(typeof(JSONString))]
    [PexMethod]
    public void TestLexer<T>([PexAssumeNotNull] T value) where T : IJSONValue {
        string json = value.ToJSONString();
        IJSONValue result = new JSONLexer().GetValue(json);

        PexAssert.AreEqual(value, result);
    }
}

Running Pex on this I found a few non-issues with null handling, which I had fixed. However, I also got a lot of methods reporting exceptions that didn't make sense. They look like this:

[TestMethod]
[PexGeneratedBy(typeof(JSONTests))]
[PexRaisedException(typeof(JSONException))]
public void TestLexerThrowsJSONException78() {
    JSONBoolean s0 = new JSONBoolean(true);
    this.TestLexer<JSONBoolean>(s0);
}

This, however, is pretty similar to one of my tests which I know works. I ran it in the debugger, and outside the debugger, and in both cases the test passed. The most boggling thing is that the exception text actually makes some sense; it's the text that would have been reported if the Constant regex didn't match the string "false". I get similar exceptions for other regex mismatches, which don't make sense.

Why does Pex think this throws an Exception? Does the instrumentation mess with ThreadLocal or Regex in a weird way? This is what my regex-holding class looks like (regexes were redacted for brevity).

private static class Regexes {
    private static RegexOptions Options = RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace;
    public static ThreadLocal<Regex> String = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
    public static ThreadLocal<Regex> Number = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
    public static ThreadLocal<Regex> Constant = new ThreadLocal<Regex>(() => new Regex(@"(...)", Options));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文