2011-04-24 4 views
8

Ho un metodo che accetta un argomento StringComparison e richiede un test unitario per dimostrare che sta eseguendo il giusto tipo di confronto.C#: Test unitario per differenziare CurrentCulture da InvariantCulture

Questo è fondamentalmente quello che ho finora. Distingue Ordinal dal resto confrontando "oe" e "œ" (vedi System.String). Tuttavia, non ho trovato un modo per differenziare CurrentCulture da 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; 
      } 
     } 
    } 
} 

ho pensato di utilizzare il problema turco confrontando "i" e "I", ma funziona solo per i confronti case-insensitive.

Mi sono guardato intorno e non sono riuscito a trovare un caso in cui InvariantCulture si differenzia da altre culture in un test di uguaglianza delle stringhe (solo ordinamento e parsing/serializzazione). Ad esempio, a seconda della cultura, "ô" e "o" si ordinano in modo diverso, ma tutte le culture restituiscono lo stesso risultato nei test di uguaglianza.

Esiste un test di uguaglianza per differenziare InvariantCulture da qualsiasi altra cultura?

MODIFICA: Il tedesco "ß" e "ss" danno lo stesso risultato per tutte le culture in modo che non funzionino.

MODIFICA: In realtà, tutto ciò che è necessario è due stringhe considerate uguali in una cultura e non uguali in un'altra.

risposta

2

Grazie a blackSphere, sono stato in grado di trovare alcune differenze tra alcune culture e l'InvariantCulture, come mostrato nel codice seguente:

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); 
} 

Purtroppo, il metodo string.Compare non sembra mostrare queste differenze. Comunque, il mio metodo di prova assomiglia a questo ora:

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); 
} 
1

Prova coté e côte con fr-FR come cultura corrente.

Oppure utilizzare this MSDN resource per trovare altri esempi.

Mi sono guardato intorno e non sono riuscito a trovare un caso in cui InvariantCulture si differenzia da altre culture per confronto di stringhe (solo ordinamento e parsing/serializzazione).

Non capisco questo commento: sicuramente l'ordinamento utilizza StringComparison.

+0

e ed o tipo diverso a seconda della cultura, ma non sembrano influenzare i test di uguaglianza, che è quello che mi serve. Ho aggiornato la domanda per cercare di essere più chiara. Grazie – drifter

+0

@drifter: hai esaminato l'esempio nella documentazione di String.IndexOf: http://msdn.microsoft.com/en-us/library/ms224425.aspx. Confronta le stringhe con \ u00c5 e \ u0061 \ u30a. Forse ti darà quello che stai cercando. – Joe

+0

Questo esempio ha gli stessi risultati per CurrentCulture e InvariantCulture. Ho provato varianti di esso in altre culture, ma senza fortuna. – drifter

3

Il campione MSDN su CultureInfo ha un esempio con diversi ordinamenti in base alla cultura. Penso che sia la tua scommessa più probabile per un posto di partenza. Tuttavia, potresti non essere in grado di sfruttare alcune delle informazioni riportate di seguito, se ciò non funziona.

Sembra che un simile insieme di test venga eseguito sulla pagina MSDN String.Compare. In questo esempio, però, è nella cultura en-US.

Se si guarda la pagina CultureInfo.InvarientCulture, si noterà che InvarientCulture si basa sull'inglese, ma senza alcuna codifica regionale o nazionale. E la pagina StringComparison menziona che i trattini hanno un peso specifico, a seconda della lingua. Potresti riuscire a trarne vantaggio trovando una lingua che pesi i trattini in modo diverso dall'inglese.

Wikipedia ha alcune note interessanti sull'ordinamento nell'articolo collation, che potrebbe anche essere utile. Guarda in particolare attraverso l'ordinamento, in ordine alfabetico, e poi guarda le note spagnole.

Ad esempio, il 29 lettere dell'alfabeto di tratta spagnolo N come una lettera base seguendo n, e precedentemente trattati ch e ll come base lettere seguenti c el, rispettivamente. Ch e ll sono ancora considerate lettere, ma sono ora in ordine alfabetico come combinazioni di due lettere .

Non sono sicuro di quanto sarà utile, ma potrebbe portare a una risposta.

+1

Grazie! Ch e ll restituiscono risultati diversi in alcune culture rispetto alla cultura invariante. Stranamente, però, non nella cultura spagnola. Ho pubblicato una risposta che dimostra queste differenze che attualmente devo contrassegnare come risposta accettata, ma è basata sulla tua. – drifter