【问题标题】:C#: Unit Test to Differentiate CurrentCulture from InvariantCultureC#:区分 CurrentCulture 和 InvariantCulture 的单元测试
【发布时间】:2011-04-24 05:52:17
【问题描述】:

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

这基本上是我目前所拥有的。它通过比较“oe”和“œ”来区分 Ordinal(参见System.String)。但是,我还没有找到区分 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;
            }
        }
    }
}

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

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

是否有用于区分 InvariantCulture 与任何其他文化的平等测试?

编辑: 德语“ß”和“ss”对所有文化都给出相同的结果,因此它们不起作用。

编辑: 实际上,只需要两个字符串在一种文化中相等,而在另一种文化中不相等。

【问题讨论】:

    标签: c# unit-testing culture


    【解决方案1】:

    CultureInfo 上的 MSDN 示例有一个示例,该示例具有不同的排序顺序,具体取决于文化。我认为这是你最有可能作为起点的赌注。但是,如果这不起作用,您也许可以利用下面的一些信息。

    似乎正在String.Compare MSDN 页面上执行一组类似的测试。但在此示例中,它是在 en-US 文化中。

    如果您查看 CultureInfo.InvarientCulture 页面,您会注意到 InvarientCulture 基于英语,但没有任何区域或国家/地区编码。 StringComparison 页面提到连字符特别具有不同的权重,具体取决于语言。您可以通过找到一种与英语不同的连字符权重的语言来利用这一点。

    维基百科在collation 文章中有一些关于排序的有趣注释,这可能也很有用。通过排序,按字母顺序仔细查看,然后查看西班牙语注释。

    例如,29 个字母的字母表 西班牙语将 ñ 视为基本字母 在 n 之后,以前处理过 ch 和 ll 作为 c 之后的基本字母 和 l,分别。 Ch 和 ll 是 仍然被认为是字母,但现在 按字母顺序排列为两个字母 组合。

    我不确定这会有多大帮助,但它可能会引导您找到答案。

    【讨论】:

    • 谢谢!与不变的文化相比,Ch 和 ll 在某些文化中返回不同的结果。奇怪的是,在西班牙文化中却没有。我发布了一个答案,展示了这些差异,我目前必须将其标记为已接受的答案,但它是基于你的。
    【解决方案2】:

    感谢 blackSphere,我能够找到一些文化和 InvariantCulture 之间的一些差异,如下面的代码所示:

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

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

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

    【讨论】:

      【解决方案3】:

      尝试以 fr-FR 作为您当前的文化的 cote 和 côte。

      或使用this MSDN resource 查找其他示例。

      我环顾四周,找不到 InvariantCulture 通过字符串比较(仅排序顺序和解析/序列化)与其他文化不同的情况。

      我不明白这条评论 - 排序顺序肯定使用 StringComparison。

      【讨论】:

      • é 和 ô 的排序因文化而异,但似乎不会影响平等测试,这正是我所需要的。我更新了问题以尝试更清楚。谢谢
      • @drifter - 您是否查看过 String.IndexOf 文档中的示例:msdn.microsoft.com/en-us/library/ms224425.aspx。它将字符串与 \u00c5 和 \u0061\u030a 进行比较。也许会给你你想要的。
      • 该示例对 CurrentCulture 和 InvariantCulture 的结果相同。我在其他文化中尝试过它的变体,但没有运气。
      猜你喜欢
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 2016-10-03
      • 2011-03-14
      • 2011-08-27
      • 1970-01-01
      • 2022-12-16
      相关资源
      最近更新 更多