0

I've been setting up a Cake script (C# Make) in preparation of automating our unit testing. I have the script set up and it's running the unit tests as expected except for one quirk...

One of the simpler tests is failing when MSTest attempts to execute it but it passes with flying colors when I run the test from VS 2013.

            [TestMethod]
        public void Field_is_XmlNode_innertext_urlencode()
        {
            // Arrange
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml("<field>\"'#</field>");
            var fetchedField = xmlDoc.SelectSingleNode("field");

            // Assert
            Assert.AreEqual("%22%27%23", CrmHelpers.GetFetchedFieldValueAsString(fetchedField, null, true));
        }

Cake script section that calls MSTest.

Task("RunTests")
.IsDependentOn("Build")
.Does(() =>
{
    Information("TestPath {0}", "./Tests/Unit Tests/**/bin/" + configuration + "/*.UnitTests.dll");
    MSTest("./Tests/Unit Tests/**/bin/" + configuration + "/*.UnitTests.dll");
});

In VS2013 the value \"'# is properly encoded to %22%27%23 however when executing the test via Cake calling MSTest that same value is encoded as %22'%23.

enter image description here enter image description here

My questions are: Why are these values encoded differently in MSTest from what I see in VS2013 when theoretically it should be running the same code? How do I correct the issue so that MSTest runs all of my unit tests in a predictable and consistent manner?

EDIT 1: Adding requested method

 public static string GetFetchedFieldValueAsString(XmlNode fetchedField, string format, bool urlEncode)
    {
        var fieldValue = "";

        if (format.IsNotEmpty())
        {
            try
            {
                if (fetchedField.Attributes["date"] != null)
                {
                    var date = DateTime.Parse(fetchedField.InnerText).ToUniversalTime();
                    fieldValue = GetFormatedDateAsString(date, format);
                }
                else if (fetchedField.InnerText.IsNumeric())
                {
                    var number = float.Parse(fetchedField.InnerText);
                    fieldValue = number.ToString(format);
                }
            }
            catch
            {
                // Ignore formating errors
            }
        }

        if (fieldValue.IsEmpty()) fieldValue = fetchedField.GetAttributeValue("name");
        if (fieldValue.IsEmpty()) fieldValue = fetchedField.GetAttributeValue("formattedvalue");
        if (fieldValue.IsEmpty() && fetchedField.Attributes["date"] != null)
        {
            var date = fetchedField.GetAttributeValue("date");
            var time = fetchedField.GetAttributeValue("time");
            if (date.IsNotEmpty()) fieldValue = date;
            if (date.IsNotEmpty() && time.IsNotEmpty()) fieldValue += " ";
            if (time.IsNotEmpty()) fieldValue += time;
        }
        if (fieldValue.IsEmpty()) fieldValue = fetchedField.InnerText;
        if (fieldValue.IsGuid()) fieldValue = fieldValue.Replace("{", "").Replace("}", "");
        fieldValue = fieldValue.Sanitize();
        if (urlEncode) fieldValue = fieldValue.UrlComponentEncode();
        return fieldValue;
    }

EDIT 2: Adding requested method

    public static string UrlComponentEncode(this string s)
    {
        return Uri.EscapeDataString(s);
    }

EDIT 3: Cake Methods to get MSTest path

    /// <summary>
    /// Gets the default tool path.
    /// </summary>
    /// <returns>The default tool path.</returns>
    protected override FilePath GetDefaultToolPath(MSTestSettings settings)
    {
        foreach (var version in new[] { "12.0", "11.0", "10.0" })
        {
            var path = GetToolPath(version);
            if (_fileSystem.Exist(path))
            {
                return path;
            }
        }
        return null;
    }

    private FilePath GetToolPath(string version)
    {
        var programFiles = _environment.GetSpecialPath(SpecialPath.ProgramFilesX86);
        var root = programFiles.Combine(string.Concat("Microsoft Visual Studio ", version, "/Common7/IDE"));
        return root.CombineWithFilePath("mstest.exe");
    }
Justin williams
  • 574
  • 1
  • 8
  • 26
  • 1
    You'd have to show the `GetFetchedFieldValueAsString` method, since that is apparently what you are testing. – Dirk Feb 04 '15 at 16:34
  • Now add the `UrlComponentEncode()` implementation, as that is the method that returns something different on your build server. – CodeCaster Feb 04 '15 at 17:16
  • @Dirk Second method added – Justin williams Feb 04 '15 at 17:20
  • I once digged into that topic when answering another question http://stackoverflow.com/questions/22013879/how-to-url-encode-strings-in-c-sharp. I found out that EscapeDataString has been changed in .NET 4.5. Maybe you target different versions with your 2 tests. – Dirk Feb 04 '15 at 17:27
  • It does seem similar. It's the ' that is the problem child however I am running .NET 4.5 in VS and it works when ran from there. Maybe I don't fully understand but it seems the opposite of the expected behavior. I'm not sure how to check what version of .NET MSTest is running against or how to configure that. I'll look into it on my own but if you have any insights into that I'd appreciate it. Thanks. – Justin williams Feb 04 '15 at 18:53
  • @Dirk Forcing Cake/MSBuild to build with a MSBuildToolVersion for VS 2013 and the same thing happens. According to the source code that would be the default though so that's not surprising. – Justin williams Feb 04 '15 at 21:16
  • Manually verified that every project is configured to run against .net 4.5 – Justin williams Feb 04 '15 at 21:20
  • @Dirk Ok, progress! I can't seem to figure out how to make MSTest run against .NET 4.5 however I can change VS2013 to test against .NET 4.0 and when I do that I get the same error! Now I just need to figure out how to get Cake to run MSTest as 4.5... – Justin williams Feb 04 '15 at 21:56
  • Do you know if the mstest is run with mstest.exe or vstest.console.exe? I haven't used cake, so I don't know which it uses. FYI, mstest.exe is the old way to run tests and vstest.console.exe is the new way.. – John Koerner Feb 04 '15 at 22:58
  • I'm afraid I can't help you further since I'm neither using Cake nor MSTest. But at least we now know why the output is different. – Dirk Feb 05 '15 at 06:52
  • @Dirk Np, thanks for helping me track down exactly what the issue was. – Justin williams Feb 05 '15 at 14:34
  • @JohnKoerner It's using MSTest.exe. I'll append those methods to the original post. – Justin williams Feb 05 '15 at 14:41
  • Call `HtmlDecode` on the string before comparing? – Peter Ritchie Feb 05 '15 at 14:48
  • @JohnKoerner Does MSTest not support .NET 4.5? You said that vstest.console.exe is the new way, is that .NET 4.5+? – Justin williams Feb 05 '15 at 16:28
  • @Justinwilliams I don't know for sure, but you could always modify your tooling to use vstest.console.exe to see if it corrects your issue. – John Koerner Feb 05 '15 at 21:41

1 Answers1

0

The solution was just don't use Cake. Going back to a PS solution.

Justin williams
  • 574
  • 1
  • 8
  • 26