Расширение класса xUnit Assert с новыми утверждениями

Я пытаюсь расширить метод xUnit assert, добавив некоторые функции Селена

namespace MyProject.Web.Specs.PageLibrary.Extensions
{
    public static class AssertExtensions
    {
        public static void ElementPresent(this Assert assert, ...)
        {
            if (...)
            {
                throw new AssertException(...);
            }
        }
    }
}

но я получаю эту ошибку компиляции, когда пытаюсь ее использовать.

using MyProject.Web.Specs.PageLibrary.Extensions;    
using Xunit;
...

public void DoSomething()
{
    Assert.ElementPresent(...);
}

ошибка

Error   5   'Xunit.Assert' does not contain a definition for 'ElementPresent'

кто-нибудь знает, возможно ли это или где я ошибаюсь?

5 ответов


вам нужен объект intance, который будет передан в качестве этого аргумента методу расширения. В вашем случае это был бы правильный синтаксис

var assert = new Assert();
assert.ElementPresent(...);

но я полагаю, что вам не нужно или даже не можете создать экземпляр класса Assert.

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

 AssertExtensions.ElementPresent(...);

Изменить 2 xUnit 2 в конечном итоге привел к перемещению утверждений в отдельную сборку. Там скомпилированы и источник всего упаковок в NuGet, и Assert класс является частичным, поэтому, используя только исходную версию пакета,Assert становится очень легко расширяемым (в C#, то есть).

редактировать для большей полноты: xUnit 2 удаляет эту точку расширения и рекомендует использовать методы расширения по линиям "беглые" библиотеки утверждений.


для полноты, вот описание "официального" способа расширения Assert (что удивительно не было упомянуто вообще, несмотря на то, что Брэд Уилсон даже присоединился к дискуссии).

из версии 1.5 (согласно блогу Брэда), xUnit.Расширения имеют явную поддержку для этого через Assertions и TestClass классы. Он работает следующим образом:

TestClass есть свойство под названием Assert это тип Assertions который передает все методы на Xunit.Assert. Потому что TestClass.Assert является экземпляром, вы можете добавить к нему методы с помощью методов расширения на Assertions:

public static class AssertionsExtensions
{
    public static void DeepEquals(this Assertions assertions, XNode expected, XNode actual)
    {
        assertions.True(XNode.DeepEquals(expected, actual)); // You can also use Assert.True here, there's effectively no difference.
    }
}

теперь вам нужно, чтобы ваш тестовый класс производный от Xunit.Extensions.TestClass (смущенно, есть также Xunit.TestClass, что не то, что вы хотите), и Assert свойство "тень"Xunit.Assert введите, если имя не указано явно.

в вашем тестовом классе, производном от TestClass, вы теперь можете использовать

Assert.DeepEquals(expectedXml, actualXml);

единственное реальное отличие от встроенного утверждения xUnit (кроме того, что синтаксическая раскраска для Assert - это идентификатор, а не тип) заключается в том, что, когда это не удается, вы просто получаете TrueException, а не конкретные DeepEqualsException это может гипотетически сказать вам здесь сравнение не удалось. Но, конечно, вы могли бы построить его таким же образом.


Извините, но вы путаетесь (EDIT:и я тоже!). xUnit.net s Assert и static и, таким образом, не могут быть добавлены расширения (хотя другие библиотеки утверждений не подают в суд на этот подход, поэтому можно ожидать использования методов расширения для расширения Assert). Так в xUnit.net Юниверс, если вы хотите добавить пользовательское утверждение, добавьте новый статический класс с другим именем.

вы можете заставить свой подход работать, изменив свой класс от:

public static class AssertExtensions
{
    public static void ElementPresent(this Assert assert, ...)

в:

public class AssertExtensions : XUnit.Assert
{
    public static void ElementPresent(...)

а затем, используя трюк @BradWilson, добавив:

using Assert = MyProject.Web.Specs.PageLibrary.Extensions.AssertExtensions; 

в верхней части любого файла, нуждающегося в ваших расширений.

этот метод удобен для добавления перегрузок, подумайте об этом....

(очевидная слабость в том, что вы не можете иметь более одного прямого доступа через Assert. хотя)


резюме решения для xUnit 2. (Работал для меня для версии 2.1.0 от NuGet.)

Assert-это частичный класс, который можно расширить, добавив другую часть. Для этого Вам необходимо скомпилировать сборку Assert из источников. Вы можете использовать xunit.утверждать.источник NuGet, чтобы получить источники.

Шаги

  1. удалить ссылка в xUnit.assert пакет NuGet от проект.
  2. установить вместо в xUnit.утверждать.источник пакета.
  3. на Xunit пространство имен, определение public partial class Assert и добавьте свои пользовательские утверждения там.

пример пользовательского утверждения:

namespace Xunit
{ 
    public partial class Assert
    {
        public static void ArraySegmentEqual<T>(
            T[] expectedSequence, T[] buffer, int offset = 0)
        {
            for (int i = 0; i < expectedSequence.Length; i++)
            {
                int b = i + offset;

                True(buffer[b].Equals(expectedSequence[i]),
                    $"Byte #{b} differs: {buffer[b]} != {expectedSequence[i]}");
            }
        }
    }
}

Примечание: другие ответы и изменения также указывают на решение, но мне потребовалось довольно много времени, чтобы понять это оттуда. Кроме того, я не утверждаю, что это единственный или лучший вариант.


на xUnit 2+:

1) Добавить xunit.assert.source пакет Nuget для проекта с расширениями.

2) Создайте частичное определение класса:

namespace xUnit
{
  public partial class Assert
  {
    public static void ElementPresent(...)
    {
    }
  }
}