Udostępnij za pośrednictwem


Konwencje dotyczące generowania, kompilowania i nazywania w Microsoft Fakes

W tym artykule omówiono opcje i problemy związane z generowaniem i kompilacją kodu Fakes oraz opisano konwencje nazewnictwa dla typów generowanych przez fakes, elementów członkowskich i parametrów.

Wymagania

Generowanie i kompilacja kodu

Konfigurowanie generowania kodu wycinków

Generowanie typów wycinków jest konfigurowane w pliku XML, który ma rozszerzenie pliku .fakes . Platforma Fakes integruje się w procesie kompilacji za pomocą niestandardowych zadań MSBuild i wykrywa te pliki w czasie kompilacji. Generator kodu Fakes kompiluje typy wycinków do zestawu i dodaje odwołanie do projektu.

Poniższy przykład ilustruje typy wycinków zdefiniowane w FileSystem.dll:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
    <Assembly Name="FileSystem"/>
</Fakes>

Filtrowanie typów

Filtry można ustawić w pliku .fakes , aby ograniczyć typy, które powinny być stubbed. Możesz dodać niezwiązaną liczbę elementów Clear, Add, Remove w elemecie StubGeneration, aby utworzyć listę wybranych typów.

Na przykład następujący plik .fakes generuje wycinki typów w obszarze System i System.IO przestrzeni nazw, ale wyklucza dowolny typ zawierający ciąg "Handle" w systemie:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" />
  <!-- user code -->
  <StubGeneration>
    <Clear />
    <Add Namespace="System!" />
    <Add Namespace="System.IO!"/>
    <Remove TypeName="Handle" />
  </StubGeneration>
  <!-- /user code -->
</Fakes>

Ciągi filtrów używają prostej gramatyki, aby zdefiniować sposób wykonywania dopasowywania:

  • Filtry są domyślnie niewrażliwe na wielkość liter; filtry wykonują dopasowywanie podciągów:

    el pasuje do "hello"

  • Dodanie ! na końcu filtru sprawia, że jest to dokładne dopasowanie z uwzględnieniem wielkości liter:

    el! nie pasuje do "hello"

    hello! pasuje do "hello"

  • Dodanie * na końcu filtru sprawia, że jest ono zgodne z prefiksem ciągu:

    el* nie pasuje do "hello"

    he* pasuje do "hello"

  • Wiele filtrów na liście rozdzielanej średnikami jest połączonych jako rozłączenie:

    el;wo pasuje do "hello" i "world"

Klasy betonowe wycinków i metody wirtualne

Domyślnie typy wycinków są generowane dla wszystkich klas, które nie są zapieczętowane. Istnieje możliwość ograniczenia typów wycinków do abstrakcyjnych klas za pomocą pliku konfiguracji .fakes :

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" />
  <!-- user code -->
  <StubGeneration>
    <Types>
      <Clear />
      <Add AbstractClasses="true"/>
    </Types>
  </StubGeneration>
  <!-- /user code -->
</Fakes>

Typy wewnętrzne

Generator kodu Fakes generuje typy podkładek i typy wycinków dla typów widocznych dla wygenerowanego zestawu Fakes. Aby utworzyć wewnętrzne typy zestawu shimmed widoczne dla Fakes i zestawu testowego, dodaj InternalsVisibleToAttribute atrybuty do shimmed kodu zestawu, który zapewnia widoczność wygenerowanego zestawu Fakes i do zestawu testowego. Oto przykład:

// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes")]
[assembly: InternalsVisibleTo("FileSystem.Tests")]

Typy wewnętrzne w silnie nazwanych zestawach

Jeśli zestaw shimmed jest silnie nazwany i chcesz uzyskać dostęp do typów wewnętrznych zestawu:

  • Zarówno zestaw testowy, jak i zestaw Fakes muszą być silnie nazwane.

  • Dodaj klucze publiczne zestawu testowego i fakes do atrybutów InternalsVisibleToAttribute w zestawach z podkładkami. Oto, jak przykładowe atrybuty w kodzie zestawu shimmed będą wyglądać, gdy zestaw shimmed jest silnie nazwany:

    // FileSystem\AssemblyInfo.cs
    [assembly: InternalsVisibleTo("FileSystem.Fakes",
        PublicKey=<Fakes_assembly_public_key>)]
    [assembly: InternalsVisibleTo("FileSystem.Tests",
        PublicKey=<Test_assembly_public_key>)]
    

Jeśli zestaw shimmed jest silnie nazwany, platforma Fakes automatycznie podpisuje wygenerowany zestaw Fakes. Musisz podpisać silny podpis zestawu testowego. Zobacz Zestawy o silnych nazwach.

Struktura Fakes używa tego samego klucza do podpisywania wszystkich wygenerowanych zestawów, więc można użyć tego fragmentu kodu jako punktu początkowego, aby dodać atrybut InternalsVisibleTo dla zestawu fakes do kodu zestawu shimmed.

[assembly: InternalsVisibleTo("FileSystem.Fakes, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e92decb949446f688ab9f6973436c535bf50acd1fd580495aae3f875aa4e4f663ca77908c63b7f0996977cb98fcfdb35e05aa2c842002703cad835473caac5ef14107e3a7fae01120a96558785f48319f66daabc862872b2c53f5ac11fa335c0165e202b4c011334c7bc8f4c4e570cf255190f4e3e2cbc9137ca57cb687947bc")]

Dla zestawu Fakes można określić inny klucz publiczny, taki jak klucz utworzony dla zestawu shimmed, określając pełną ścieżkę do pliku snk, który zawiera klucz alternatywny jako KeyFile wartość atrybutu w\FakesCompilation elemencie pliku .fakes. Na przykład:

<-- FileSystem.Fakes.fakes -->
<Fakes ...>
  <Compilation KeyFile="full_path_to_the_alternate_snk_file" />
</Fakes>

Następnie musisz użyć klucza publicznego alternatywnego pliku snk jako drugiego parametru atrybutu InternalVisibleTo dla zestawu Fakes w kodzie zestawu shimmed:

// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes",
    PublicKey=<Alternate_public_key>)]
[assembly: InternalsVisibleTo("FileSystem.Tests",
    PublicKey=<Test_assembly_public_key>)]

W powyższym przykładzie wartości Alternate_public_key i wartości Test_assembly_public_key mogą być takie same.

Optymalizowanie czasów kompilacji

Kompilacja zestawów Fakes może znacznie zwiększyć czas kompilacji. Czas kompilacji można zminimalizować, generując zestawy Fakes dla zestawów .NET System i zestawów innych firm w osobnym scentralizowanym projekcie. Ponieważ takie zestawy rzadko zmieniają się na maszynie, można ponownie użyć wygenerowanych zestawów Fakes w innych projektach.

Z projektów testów jednostkowych dodaj odwołanie do skompilowanych zestawów Fakes, które są umieszczane w folderze projektu FakesAssemblies.

  1. Utwórz nową bibliotekę klas z wersją środowiska uruchomieniowego platformy .NET zgodną z projektami testowymi. Nazwijmy to Fakes.Prebuild. Usuń plik class1.cs z projektu, który nie jest potrzebny.

  2. Dodaj odwołanie do wszystkich zestawów systemowych i innych firm, dla których potrzebujesz aplikacji Fakes.

  3. Dodaj plik .fakes dla każdego zestawu i kompilacji.

  4. Z projektu testowego

    • Upewnij się, że masz odwołanie do biblioteki DLL środowiska uruchomieniowego Fakes:

      %ProgramFiles(x86)%\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.QualityTools.Testing.Fakes.dll

    • Dla każdego zestawu, dla którego utworzono narzędzia Fakes, dodaj odwołanie do odpowiedniego pliku DLL w folderze Fakes.Prebuild\FakesAssemblies projektu.

Unikaj starcia nazw zestawów

W środowisku kompilacji zespołowej wszystkie dane wyjściowe kompilacji są scalane z jednym katalogiem. Jeśli wiele projektów używa fakes, może się zdarzyć, że zestawy Fakes z różnych wersji przesłaniają się nawzajem. Na przykład podróbki TestProject1 mscorlib.dll z programów .NET Framework 2.0 i TestProject2 mscorlib.dll dla platformy .NET Framework 4 dałyby wynik do biblioteki mscorlib. zestaw Fakes.dll Fakes.

Aby uniknąć tego problemu, fakes powinien automatycznie utworzyć kwalifikowane nazwy zestawów Fakes dla odwołań nieprojektowych podczas dodawania plików .fakes . Kwalifikowana wersja nazwa zestawu Fakes osadza numer wersji podczas tworzenia nazwy zestawu Fakes:

Biorąc pod uwagę zestaw MyAssembly i wersję 1.2.3.4, nazwa zestawu Fakes to MyAssembly.1.2.3.4.Fakes.

Tę wersję można zmienić lub usunąć, edytując atrybut Version elementu Assembly w pliku .fakes:

attribute of the Assembly element in the .fakes:
<Fakes ...>
  <Assembly Name="MyAssembly" Version="1.2.3.4" />
  ...
</Fakes>

Konwencje nazewnictwa fakes

Konwencje nazewnictwa typów podkładek i wycinków

Przestrzenie nazw

  • . Sufiks fakes jest dodawany do przestrzeni nazw.

    Na przykład System.Fakes przestrzeń nazw zawiera typy podkładek przestrzeni nazw systemu.

  • Global.Fakes zawiera typ podkładki pustej przestrzeni nazw.

    Nazwy typów

  • Prefiks podkładki jest dodawany do nazwy typu w celu skompilowania nazwy typu podkładki.

    Na przykład ShimExample jest typem podkładki typu Example.

  • Prefiks wycinków jest dodawany do nazwy typu w celu skompilowania nazwy typu wycinkowego.

    Na przykład StubIExample jest typem wycinkowym typu IExample.

    Argumenty typu i zagnieżdżone struktury typów

  • Argumenty typu ogólnego są kopiowane.

  • Struktura typu zagnieżdżonego jest kopiowana dla typów podkładek.

Podkładka delegowana właściwość lub konwencje nazewnictwa pól delegata wycinków

Podstawowe reguły nazewnictwa pól, zaczynając od pustej nazwy:

  • Nazwa metody jest dołączana.

  • Jeśli nazwa metody jest jawną implementacją interfejsu, kropki zostaną usunięte.

  • Jeśli metoda jest ogólna, n jest dołączany,Of gdzie n jest liczbą argumentów metody ogólnej.

    Specjalne nazwy metod, takie jak getter właściwości lub metody ustawiania, są traktowane zgodnie z opisem w poniższej tabeli:

Jeśli metoda jest... Przykład Dołączona nazwa metody
Konstruktor .ctor Constructor
Konstruktor statyczny .cctor StaticConstructor
Metoda dostępu zawierająca nazwę metody składającą się z dwóch części oddzielonych ciągiem "_" (na przykład metod getters właściwości) kind_name (typowy przypadek, ale nie wymuszany przez ECMA) NameKind, gdzie obie części zostały skapitalizowane i zamienione
Getter właściwości Prop PropGet
Setter właściwości Prop PropSet
Dodatek zdarzeń Add
Usuwanie zdarzeń Remove
Operator składający się z dwóch części op_name NameOp
Na przykład: + operator op_Add AddOp
W przypadku operatora konwersji typ zwracany jest dołączany. T op_Implicit ImplicitOpT

Uwaga

  • Metody pobierające i ustawiacze indeksatorów są traktowane podobnie jak właściwość . Domyślną nazwą indeksatora jest Item.
  • Nazwy typów parametrów są przekształcane i łączone.
  • Zwracany typ jest ignorowany, chyba że istnieje niejednoznaczność przeciążenia. Jeśli występuje niejednoznaczność przeciążenia, zwracany typ jest dołączany na końcu nazwy.

Konwencje nazewnictwa typów parametrów

Dany Dołączony ciąg jest...
TypT T

Przestrzeń nazw, struktura zagnieżdżona i ogólne tics są porzucane.
Parametr wyjściowyout T TOut
Parametr ref ref T TRef
Typ tablicyT[] TArray
Wielowymiarowy typ tablicyT[ , , ] T3
Typ wskaźnikaT* TPtr
Typ ogólnyT<R1, ...> TOfR1
Argument !i typu ogólnego typu typuC<TType> Ti
Ogólny argument!!i metody metody M<MMethod> Mi
Typ zagnieżdżonyN.T N jest dołączany, a następnie T

Reguły cykliczne

Następujące reguły są stosowane rekursywnie:

  • Ponieważ fakes używa języka C# do generowania zestawów Fakes, każdy znak, który wygenerowałby nieprawidłowy token języka C#, zostanie uniknięty do znaku "_" (podkreślenie).

  • Jeśli wynikowa nazwa zderza się z dowolnym elementem członkowskim typu deklarowanego, schemat numeracji jest używany przez dołączenie dwucyfrowego licznika, zaczynając od 01.

Wykorzystanie fałszywych elementów firmy Microsoft w ciągłej integracji

Microsoft Fakes Assembly Generation

Microsoft Fakes to funkcja dostępna wyłącznie w programie Visual Studio Enterprise. W związku z tym generowanie zestawów Fakes wymaga użycia zadania kompilacji programu Visual Studio podczas kompilowania projektu.

Uwaga

Alternatywna strategia polega na sprawdzeniu zestawów fakes bezpośrednio w systemie ciągłej integracji i wykorzystaniu zadania MSBuild. Jeśli zdecydujesz się na to podejście, musisz uwzględnić odwołanie do zestawu wygenerowanego zestawu Fakes w projekcie testowym, jak pokazano w poniższym fragmencie kodu:

<Project Sdk="Microsoft.NET.Sdk">
    <ItemGroup>
        <Reference Include="FakesAssemblies\System.Fakes.dll"/>
    </ItemGroup>
</Project>

To odwołanie należy dodać ręcznie, szczególnie w przypadku projektów w stylu zestawu SDK (czyli .NET Core, .NET 5+i .NET Framework), ponieważ te projekty teraz niejawnie dodają odwołania do zestawów. Jeśli zdecydujesz się użyć tej metody, pamiętaj, aby zaktualizować zestaw Fakes za każdym razem, gdy zestaw nadrzędny przejdzie zmiany.