C#:将CurrentCulture与InvariantCulture区分开来的单元测试

dri*_*ter 8 c# culture unit-testing

我有一个采用StringComparison参数的方法,它确实需要一个单元测试来证明它正在执行正确的比较类型.

这基本上是我到目前为止所做的.它通过比较"oe"和"œ"(参见System.String)将Ordinal与其余部分区分开来.但是,我没有找到区分CurrentCulture和InvariantCulture的方法.

using System;
using NUnit.Framework;
using System.Threading;
using System.Globalization;

namespace NUnitTests
{
    [TestFixture]
    public class IndexOfTests
    {
        [Test]
        public void IndexOf_uses_specified_comparison_type()
        {
            StringComparison comparisonTypePerformed;

            result = TestComparisonType(StringComparison.CurrentCulture);
            Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);

            result = TestComparisonType(StringComparison.InvariantCulture);
            Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);

            result = TestComparisonType(StringComparison.Ordinal);
            Assert.AreEqual(StringComparison.CurrentCulture, comparisonTypePerformed);
        }

        bool TestComparisonType(StringComparison comparisonType)
        {
            int result;

            // Ensure the current culture is consistent for test
            var prevCulture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);

            try
            {
                result = IndexOf("oe", "œ", comparisonType);
                if (result == 0)
                {
                    // The comparison type performed was either CurrentCulture,
                    // InvariantCulture, or one of the case-insensitive variants.

                    // TODO: Add test to differentiate between CurrentCulture and InvariantCulture
                    throw new NotImplementedException();
                    result = IndexOf("???????", "???????", StringComparison.CurrentCulture);

                    //...
                }
                else // result == -1
                {
                    // The comparison type performed was either Ordinal or OrdinalIgnoreCase

                    result = IndexOf("a", "A", StringComparison.CurrentCulture);
                    if (result)
                        Console.WriteLine("Comparison type was OrdinalIgnoreCase");
                    else
                        Console.WriteLine("Comparison type was Ordinal");
                }
            }
            finally
            {
                Thread.CurrentThread.CurrentCulture = prevCulture;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我考虑通过比较"i"和"I"来使用土耳其语问题,但它仅适用于不区分大小写的比较.

我环顾四周,找不到InvariantCulture在字符串相等测试(仅排序和解析/序列化)中与其他文化不同的情况.例如,根据文化,"ô"和"o"的排序方式不同,但所有文化在相等测试中都会返回相同的结果.

是否存在将InvariantCulture与任何其他文化区分开来的平等测试?

编辑:德语"ß"和"ss"给所有文化带来相同的结果,因此它们不起作用.

编辑:真的,所需要的只是在一种文化中被认为是相同的两个字符串,而在另一种文化中则是不相等的.

dri*_*ter 3

感谢 blackSphere,我能够发现某些文化和 InvariantCulture 之间的一些差异,如以下代码所示:

\n\n
void Demonstration_For_LL()\n{\n    int foundPos;\n\n    foundPos = "ll".IndexOf("l", StringComparison.InvariantCulture);\n    Assert.AreEqual(0, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("sq", false);\n    foundPos = "ll".IndexOf("l", StringComparison.CurrentCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("sq-AL", false);\n    foundPos = "ll".IndexOf("l", StringComparison.CurrentCulture);\n    Assert.AreEqual(-1, foundPos);\n}\n\nvoid Demonstration_For_CH()\n{\n    int foundPos;\n\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(0, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("cs", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("cs-CZ", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("sk", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("sk-SK", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("vi", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n\n    Thread.CurrentThread.CurrentCulture = new CultureInfo("vi-VN", false);\n    foundPos = "ch".IndexOf("c", StringComparison.InvariantCulture);\n    Assert.AreEqual(-1, foundPos);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是, string.Compare 方法似乎没有显示这些差异。无论如何,我的测试方法现在看起来像这样:

\n\n
class Example\n{\n    public static void Main()\n    {\n        var comparisonTypePerformed =\n            GetComparisonTypePerformed(\n                new TestedMethod(string.IndexOf));\n\n        Console.WriteLine("Comparison type performed was: " + comparisonTypePerformed);\n    }\n\n    public static StringComparison GetComparisonTypePerformed(TestedMethod testedMethod)\n    {\n        StringComparison comparisonTypePerformed;\n\n        var prevCulture = Thread.CurrentThread.CurrentCulture;\n        try\n        {\n            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);\n\n            // Check if method performs an Ordinal search\n            int result = testedMethod("\xc5\x93", "oe", 0, 1, comparisonType);\n\n            if (result == StringHelper.NPOS)\n            {\n                // Check if method performs a case-sensitive search\n                result = testedMethod("a", "A", 0, 1, comparisonType);\n\n                if (result == StringHelper.NPOS)\n                    comparisonTypePerformed = StringComparison.Ordinal;\n                else\n                    comparisonTypePerformed = StringComparison.OrdinalIgnoreCase;\n            }\n            else\n            {\n                Thread.CurrentThread.CurrentCulture = new CultureInfo("sq-AL", false);\n\n                // Check if method uses CurrentCulture or InvariantCulture\n                result = testedMethod("ll", new string[] { "l" }, 0, 2, comparisonType);\n\n                if (result == StringHelper.NPOS)\n                {\n                    // Check if method performs a case-sensitive search\n                    result = testedMethod("a", new string[] { "A" }, 0, 1, comparisonType);\n\n                    if (result == StringHelper.NPOS)\n                        comparisonTypePerformed = StringComparison.CurrentCulture;\n                    else\n                        comparisonTypePerformed = StringComparison.CurrentCultureIgnoreCase;\n                }\n                else\n                {\n                    // Check if method performs a case-sensitive search\n                    result = testedMethod("a", new string[] { "A" }, 0, 1, comparisonType);\n\n                    if (result == StringHelper.NPOS)\n                        comparisonTypePerformed = StringComparison.InvariantCulture;\n                    else\n                        comparisonTypePerformed = StringComparison.InvariantCultureIgnoreCase;\n                }\n            }\n        }\n        finally\n        {\n            Thread.CurrentThread.CurrentCulture = prevCulture;\n        }\n\n        return comparisonTypePerformed;\n    }\n\n    delegate int TestedMethod(string source, string value, int startIndex, int count, StringComparison comparisonType);\n}\n
Run Code Online (Sandbox Code Playgroud)\n