У меня есть простой класс лексера JSON; он принимает string
и генерирует IJSONValue
; IJSONValue
имеет метод ToJSONString
, который возвращает допустимую строку JSON.
Код для этого, конечно, довольно сложный с большим количеством веток; вот почему я подумал, что это будет идеальным местом для проверки способностей Пекса. Я создал следующий тест:
[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"
. Я получаю аналогичные исключения для других несоответствий регулярных выражений, которые не имеют смысла.
Почему Пекс думает, что это вызывает исключение? Приборы странным образом связываются с 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));
}