2013-04-24 15 views
7

Próbuję rozszerzyć metodę xUnit wymuszenia dodając niektóre funkcje selenuRozszerzanie klasy xUnit Assert z nowym twierdzi

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

Ale otrzymuję ten błąd kompilacji, gdy próbuję go użyć.

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

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

a błąd

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

Czy ktoś wie, czy jest to możliwe, lub gdzie jadę nie tak?

Odpowiedz

3

Potrzebna jest intencja obiektu, która zostanie przekazana jako ten argument do metody rozszerzenia. W twoim przypadku będzie to poprawna składnia

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

Ale przypuszczam, że nie trzeba, a nawet nie można utworzyć instancję klasy Assert.

Próbujesz wywołać metodę rozszerzenia jako wywołanie statyczne w rozszerzonej klasie i to nie będzie działać. Ale dlaczego nie po prostu zadzwonić

AssertExtensions.ElementPresent(...); 
+0

Dzięki, że wyjaśnia, dlaczego nie mogę dostać assert przedłużyć jak chciałem. Twoje rozwiązanie jest prawie tym, co w końcu robiłem, ale nazwałem moje 'SeleniumAssert.ElementPresent (...);' – Neil

+1

Dla xUnit 2, sprawdź przykłady, takie jak https://github.com/xunit/samples.xunit /blob/master/AssertExtensions/StringAssertionExtensions.cs – Jedidja

3

Niestety, ale jesteś coraz mylić (EDIT: i tak było I). xUnit.net to Assert jest static i dlatego nie może mieć dodanych rozszerzeń (chociaż inne biblioteki Asercji nie pozują tego podejścia, dlatego można się spodziewać użycia metod rozszerzeń w celu rozszerzenia Assert). Tak więc w świecie xUnit.net, jeśli chcesz dodać niestandardową asercję, dodaj nową klasę statyczną o innej nazwie.

Można zrobić swoją pracę podejście zmienia swoją klasę od:

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

do:

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

a następnie przy użyciu @ trik BradWilson za dodania:

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

w szczyt dowolnego pliku wymagającego rozszerzeń.

Technika ta jest przydatna do dodawania przeciążeń przyjść myśleć o nim ....

(Oczywistą słabością jest to, że nie można mieć więcej niż jedno bezpośrednio dostępny poprzez Assert. chociaż)

+0

Klasa "Assert" nie jest statyczna, ale metody wewnątrz są statyczne, to właśnie mnie wyrzucało. Zobacz rozwiązanie @jure – Neil

+0

@Neil. Dzięki za upadek. Rozmawiam z @xunitem, sprawdzając, czy 'Assert' może stać się klasą statyczną, aby uniknąć sytuacji, w której ktoś inny będzie działał (jest to dla mnie niespodzianką, że nie jest tak, ponieważ xUnit.net zależy od .NET 2.0, która pozwala na klasy statyczne i nie mogę Zastanówcie się, jak zmiana może być zerwana.) –

+0

@Neil Ah, wydaje się, że mogło być pozostawione otwarte, aby umożliwić opisaną sztuczkę rozszerzenia [tutaj] (https://xunit.codeplex.com/discussions/15792). W końcu powód, dla którego byłam tak pewna, że ​​jest "statyczna" - sam Brad Wilson powiedział mi, że to było: - https://xunit.codeplex.com/discussions/238521 –

10

Edycja 2 xUnit 2 ostatecznie zakończyło przenoszenie twierdzeń do osobnego zespołu. W NuGet są to pakiety zarówno skompilowane, jak i źródłowe, a klasa Assert jest częściowa, więc używając tylko wersji źródłowej pakietu, Assert staje się bardzo łatwo rozszerzalna (w języku C#).

Edit Więcej kompletności: xUnit 2 usuwa ten punkt rozszerzenia i zaleca stosowanie metod przedłużenie wzdłuż linii „biegle” bibliotek twierdzenia.


Dla kompletności, oto opis „oficjalny” sposób przedłużenia Assert (który nieoczekiwanie nie została wymieniona w ogóle, pomimo faktu, że Brad Wilson nawet dołączył do dyskusji).

Od wersji 1.5 (zgodnie z blogem Brada), xUnit.Extensions ma jawną obsługę tego poprzez klasy Assertions i TestClass. To działa tak:

TestClass ma właściwość o nazwie Assert że jest typu Assertions który przekierowuje wszystkie metody na Xunit.Assert. Ponieważ TestClass.Assert jest instancją, można dodać metod do niego za pomocą metod wewnętrznych na 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. 
    } 
} 

Teraz trzeba mieć klasa testy pochodzą z Xunit.Extensions.TestClass (myląco, istnieje również Xunit.TestClass, który jest nie to, co chcesz), a właściwość Assert "zasłoni" typ Xunit.Assert, jeśli nie zostanie jawnie zakwalifikowana nazwa.

w klasie testowej, która wywodzi się z TestClass można teraz używać

Assert.DeepEquals(expectedXml, actualXml); 

Jedyną prawdziwą różnicę z wbudowaną xUnit twierdzenie (oprócz faktu, że kolorowania dla Assert składnia jest, że z identyfikatorem , a nie typ) polega na tym, że gdy się nie powiedzie, otrzymujesz po prostu TrueException, a nie konkretną DeepEqualsException, która może hipotetycznie powiedzieć, że porównanie nie powiodło się. Ale oczywiście możesz to zbudować w ten sam sposób.

+0

Zobacz post Rubena Bartelinka .. poniżej. Razem z wiedzą tutaj powstaje twoja własna pochodna z globalnego :: XUnit.Assert – Robetto

+1

. Dla xUnit 2, najłatwiej jest sprawdzić przykłady takie jak https://github.com/xunit/samples.xunit /blob/master/AssertExtensions/StringAssertionExtensions.cs – Jedidja

3

Podsumowanie rozwiązania dla xUnit 2. (Opracowano dla mnie wersję 2.1.0 z NuGet.)

Assert jest klasą częściową, którą można rozszerzyć, dodając kolejną część. Aby to zrobić, musisz skompilować zespół Assert ze źródeł. Możesz użyć xunit.assert.source NuGet, aby pobrać źródła.

Kroki

  1. Usuń odniesienie do xunit.assert Nuget pakiet z projektu.
  2. Zamiast tego należy zainstalować pakiet xunit.assert.source.
  3. W przestrzeni nazw Xunit zdefiniuj public partial class Assert i dodaj tam swoje niestandardowe wstawki.

Przykład niestandardową 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]}"); 
      } 
     } 
    } 
} 

Uwaga: Inne odpowiedzi i zmiany również wskazać na rozwiązanie, ale zajęło mi sporo tom zrozumieć to stamtąd. Ponadto nie twierdzę, że jest to jedyna lub najlepsza opcja.

0

Dla xUnit 2+:

1) Dodaj xunit.assert.source pakiet Nuget do projektu z rozszerzeniami.

2) Utwórz częściową definicję klasy:

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