diff --git a/resharper/src/xunitcontrib.runner.resharper.provider/UnitTestElementFactory.cs b/resharper/src/xunitcontrib.runner.resharper.provider/UnitTestElementFactory.cs index 0e90ad9..66f51cf 100644 --- a/resharper/src/xunitcontrib.runner.resharper.provider/UnitTestElementFactory.cs +++ b/resharper/src/xunitcontrib.runner.resharper.provider/UnitTestElementFactory.cs @@ -7,6 +7,7 @@ using JetBrains.ReSharper.UnitTestFramework.Elements; using Xunit.Sdk; using JetBrains.Util; +using XunitContrib.Runner.ReSharper.RemoteRunner; namespace XunitContrib.Runner.ReSharper.UnitTestProvider { @@ -143,7 +144,8 @@ public XunitTestTheoryElement GetOrCreateTestTheory(IProject project, XunitTestM private static string GetTestTheoryShortName(string theoryName, XunitTestMethodElement methodElement) { var prefix = methodElement.TypeName.FullName + "."; - return theoryName.StartsWith(prefix) ? theoryName.Substring(prefix.Length) : theoryName; + var name = theoryName.StartsWith(prefix) ? theoryName.Substring(prefix.Length) : theoryName; + return DisplayNameUtil.Escape(name); } private static string GetTestTheoryId(XunitTestMethodElement methodElement, string shortName) diff --git a/resharper/src/xunitcontrib.runner.resharper.runner/DisplayNameUtil.cs b/resharper/src/xunitcontrib.runner.resharper.runner/DisplayNameUtil.cs new file mode 100644 index 0000000..fe5aba4 --- /dev/null +++ b/resharper/src/xunitcontrib.runner.resharper.runner/DisplayNameUtil.cs @@ -0,0 +1,50 @@ +using System; +using System.Text; + +namespace XunitContrib.Runner.ReSharper.RemoteRunner +{ + public class DisplayNameUtil + { + public static string Escape(string name) + { + var sb = new StringBuilder(); + foreach (var c in name) + sb.Append(EscapeControlChar(c)); + + return sb.ToString(); + } + + private static string EscapeControlChar(char c) + { + switch (c) + { + case '\0': + return "\\0"; + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\f': + return "\\f"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + + case '\x0085': + case '\x2028': + case '\x2029': + return string.Format("\\x{0:X4}", (ushort)c); + + default: + return char.IsControl(c) || (ushort)c > 128 + ? String.Format("\\x{0:X4}", (ushort)c) + : c.ToString(); + } + } + } +} \ No newline at end of file diff --git a/resharper/src/xunitcontrib.runner.resharper.runner/TaskProvider.cs b/resharper/src/xunitcontrib.runner.resharper.runner/TaskProvider.cs index 8a3e9ca..141a89d 100644 --- a/resharper/src/xunitcontrib.runner.resharper.runner/TaskProvider.cs +++ b/resharper/src/xunitcontrib.runner.resharper.runner/TaskProvider.cs @@ -102,7 +102,8 @@ public TheoryTaskInfo GetTheoryTask(string name, string type, string method) private static string GetTheoryShortName(string name, string type) { var prefix = type + "."; - return name.StartsWith(prefix) ? name.Substring(prefix.Length) : name; + var shortName = name.StartsWith(prefix) ? name.Substring(prefix.Length) : name; + return DisplayNameUtil.Escape(shortName); } private static bool IsTheory(string name, string type, string method) diff --git a/resharper/src/xunitcontrib.runner.resharper.runner/xunitcontrib.runner.resharper.runner.8.2.csproj b/resharper/src/xunitcontrib.runner.resharper.runner/xunitcontrib.runner.resharper.runner.8.2.csproj index a0e89d0..34f7a82 100644 --- a/resharper/src/xunitcontrib.runner.resharper.runner/xunitcontrib.runner.resharper.runner.8.2.csproj +++ b/resharper/src/xunitcontrib.runner.resharper.runner/xunitcontrib.runner.resharper.runner.8.2.csproj @@ -55,6 +55,7 @@ Properties\ProductInfo.ReSharper.8.2.cs + diff --git a/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.cs b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.cs new file mode 100644 index 0000000..3563465 --- /dev/null +++ b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.cs @@ -0,0 +1,19 @@ +using Xunit; +using Xunit.Extensions; + +namespace Foo +{ + public class PassingTheory + { + [Theory] + [InlineData("$ \\ \b \f \n \r \t \v")] + public void TestMethod(string value) + { + } + } +} + +// xunit2 doesn't define Xunit.Extensions +namespace Xunit.Extensions +{ +} diff --git a/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit1.dll.gold b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit1.dll.gold new file mode 100644 index 0000000..dcfb1dd --- /dev/null +++ b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit1.dll.gold @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit2.dll.gold b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit2.dll.gold new file mode 100644 index 0000000..c625ac0 --- /dev/null +++ b/resharper/test/data/Runner/Gold/EscapedDataAttributeStrings.xunit2.dll.gold @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resharper/test/src/tests/AcceptanceTests/Runner/OrderedFactGoldTests.cs b/resharper/test/src/tests/AcceptanceTests/Runner/OrderedFactGoldTests.cs index 6896d01..34ec409 100644 --- a/resharper/test/src/tests/AcceptanceTests/Runner/OrderedFactGoldTests.cs +++ b/resharper/test/src/tests/AcceptanceTests/Runner/OrderedFactGoldTests.cs @@ -46,5 +46,11 @@ public void TestAmbiguouslyNamedTestMethods() // TODO: This misses a test to continue running next class. Ordering. DoOneTestWithStrictOrdering("AmbiguouslyNamedTestMethods"); } + + [Test] + public void TestEscapedStringsInDataAttributes() + { + DoOneTestWithStrictOrdering("EscapedDataAttributeStrings"); + } } } \ No newline at end of file