2014-10-15 2 views
4

У меня есть некоторые объекты, которые попадают в очередь. Все объекты в очереди реализуют один и тот же базовый интерфейс, который также требует, чтобы они реализовали IEquatable <>.NUnit CollectionAssert.AreEqual (ожидается, актуально) vs Assert.IsTrue (ожидается.SequenceEqual (актуально))

Я хочу проверить, что правильные объекты помещаются в очередь в правильном порядке.

Когда я пишу тест, который делает утверждение CollectionAssert.AreEqual(expected,actual), тест не пройден, заявив, что, в то время как очередь ожидаемая длина, она отличается по индексу 0.

Однако, когда я пишу тест утверждение как Assert.IsTrue(expected.SequenceEqual(actual)) , тест проходит.

Мне кажется, что эти два утверждения должны быть одинаковыми, но, по-видимому, они совершенно разные.

Сайт NUnit не очень подробно описывает методы сбора данных, а документация Linq, хотя и более подробно, на самом деле не помогает, не имея возможности сравнить с тем, что NUnit делает с помощью метода assert.

Как эти два утверждения отличаются?

Edit - Добавление деталей

Вот код испытуемый, а также два теста, которые я бы ожидать, чтобы иметь тот же результат.

public enum ArgumentTypeEnum 
{ 
    SpiceworksDbName, 
    DestinationDbName, 
    DestinationServerName 
} 

public interface IArgument : IEquatable<IArgument> 
{ 
} 

public interface ICommandArgument : IArgument 
{ 
    ArgumentTypeEnum ArgumentType { get; } 
} 

internal interface IValueArgument : IArgument 
{ 
    String ArgumentValue { get; } 
} 

public class CommandArgument : ICommandArgument 
{ 
    public CommandArgument(ArgumentTypeEnum argumentType) { 
     ArgumentType = argumentType; 
    } 

    public ArgumentTypeEnum ArgumentType { get; private set; } 

    public bool Equals(IArgument other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 

     var otherAsCommandArg = other as CommandArgument; 
     if (otherAsCommandArg == null) 
     { 
      return false; 
     } 

     return ArgumentType == otherAsCommandArg.ArgumentType; 
    } 
} 

public class ValueArgument : IValueArgument 
{ 
    public ValueArgument(String argumentValue) 
    { 
     ArgumentValue = argumentValue; 
    } 

    public string ArgumentValue { get; private set; } 

    public bool Equals(IArgument other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 

     var otherAsValueArg = other as ValueArgument; 
     if (otherAsValueArg == null) 
     { 
      return false; 
     } 

     return ArgumentValue == otherAsValueArg.ArgumentValue; 
    } 
} 

public class Tokenizer 
{ 
    public Queue<IArgument> TokenizeArguments(string[] args) { 
     var tokenQueue = new Queue<IArgument>(); 
     args.ToList().ForEach((arg) => { 
       if (arg.StartsWith("-")) 
       { 
        switch (arg) 
        { 
         case "-sd": 
          tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName)); 
          break; 
         case "-dd": 
          tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName)); 
          break; 
         case "-ds": 
          tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName)); 
          break; 
         default: 
          tokenQueue.Enqueue(new ValueArgument(arg)); 
          break; 
        } 
       } 
       else 
       { 
        tokenQueue.Enqueue(new ValueArgument(arg)); 
       } 
      }); 
     return tokenQueue; 
    } 
} 

[TestFixture] 
public class TokenizerSpecs 
{ 
    ///Passes 
    [Test] 
    public void Tokenizer_MultipleCommandsAndValues_TokenizesAsExpected1() { 
     var args = new[] 
     { 
      "-sd", @"\\some\Directory\foo.db", "-dd", "some database name", "-ds", "Server.name", "somerandomarg", 
      "-unreconized" 
     }; 
     var t = new Tokenizer(); 
     var actualResult = t.TokenizeArguments(args); 

     var expectedResult = new Queue<IArgument>(); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName)); 
     expectedResult.Enqueue(new ValueArgument(@"\\some\Directory\foo.db")); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName)); 
     expectedResult.Enqueue(new ValueArgument("some database name")); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName)); 
     expectedResult.Enqueue(new ValueArgument("Server.name")); 
     expectedResult.Enqueue(new ValueArgument("somerandomarg")); 
     expectedResult.Enqueue(new ValueArgument("-unreconized")); 

     Assert.IsTrue(expectedResult.SequenceEqual(actualResult)); 
    } 

    ///Fails 
    [Test] 
    public void Tokenizer_MultipleCommandsAndValues_TokenizesAsExpected2() 
    { 
     var args = new[] 
     { 
      "-sd", @"\\some\Directory\foo.db", "-dd", "some database name", "-ds", "Server.name", "somerandomarg", 
      "-unreconized" 
     }; 
     var t = new Tokenizer(); 
     var actualResult = t.TokenizeArguments(args); 

     var expectedResult = new Queue<IArgument>(); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName)); 
     expectedResult.Enqueue(new ValueArgument(@"\\some\Directory\foo.db")); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName)); 
     expectedResult.Enqueue(new ValueArgument("some database name")); 
     expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName)); 
     expectedResult.Enqueue(new ValueArgument("Server.name")); 
     expectedResult.Enqueue(new ValueArgument("somerandomarg")); 
     expectedResult.Enqueue(new ValueArgument("-unreconized")); 

     CollectionAssert.AreEqual(expectedResult, actualResult); 
    } 
} 
+0

Быстрый тест с двумя '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' Может быть, вы должны показать некоторые подробности. –

+0

Звучит неплохо. Вскоре я добавлю несколько подробностей. – Joe

ответ

3

Я ознакомился с исходным кодом NUnit и, похоже, у вас есть ошибка. Сравнение осуществляется с помощью NUnitEqualityComparer.EnumerablesEqual, который затем сравнивает каждый элемент на NUnitEqualityComparer.ObjectsEqual. Мы можем сделать простой тест с использованием этого объекта:

var n = new NUnitEqualityComparer(); 
var tolerance = Tolerance.Zero; 
var equal = n.AreEqual(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName), 
         new CommandArgument(ArgumentTypeEnum.SpiceworksDbName), 
         ref tolerance); 

Этот тест возвращает false!

Как-то ObjectsEqual не попадает в метод Equals объекта. Это потребует отладки от исходного кода, чтобы выяснить, почему, но этот тест достаточно доказывает, что ошибка связана с этим.

+0

Очень интересно! Итак, метод, который я предложил (используя SequenceEqual), является безопасным путем? Любая идея, каковы пределы этой ошибки? Считаете ли вы, что проблема затрагивает все сравнения всех объектов, реализующих IEquatable? – Joe

+1

Кажется, так. Зная это, я бы обязательно использовал 'SequenceEqual'. Я не могу понять влияние этой ошибки, но она выглядит довольно серьезной. –

+2

В ответ на это я представил вопрос на странице NUnit Github. – Joe

Смежные вопросы