Udostępnij przez


Konwencje generowania, kompilacji i nazewnictwa kodu w aplikacji Microsoft Fakes

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

Wymagania

Generowanie i kompilacja kodu

Konfigurowanie generowania kodu stubó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 stubó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ć zastępowane. 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 atrybuty dla typów w przestrzeniach nazw System i System.IO, ale wyklucza dowolny typ zawierający ciąg "Handle" w przestrzeni nazw System.

<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 ciągów znaków:

    el pasuje do "cześć"

  • 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 "witaj"

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

    el* nie pasuje do "hello"

    he* pasuje do "cześć"

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

    el;wo pasuje do "cześć" i "świat"

Klasy szkieletowe 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 zawiasowe i typy szkieletowe dla typów widocznych w wygenerowanym zestawie Fakes. Aby uczynić wewnętrzne typy zestawu shimmed widocznymi dla Fakes i zestawu testowego, dodaj atrybuty InternalsVisibleToAttribute, które zapewniają widoczność dla wygenerowanego zestawu Fakes i zestawu testowego, do kodu zestawu shimmed. Oto przykład:

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

Typy wewnętrzne w silnie nazwanych assembliach

Jeśli zestaw z podkładką ma silną nazwę i chcesz uzyskać dostęp do typów wewnętrznych tego zestawu:

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

  • Dodaj klucze publiczne zestawów testowego i Fakes do atrybutów InternalsVisibleToAttribute w zashimowanych zestawach. 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 shimed, poprzez podanie pełnej ścieżki do pliku .snk, który zawiera klucz alternatywny, jako wartość atrybutu KeyFile w elemencie Fakes\Compilation pliku .fakes. 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 systemu .NET 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 pakietów systemowych i zewnętrznych, dla których potrzebujesz Fakes.

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

  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, do którego utworzono 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 wyniki kompilacji są scalane w jednym katalogu. Jeśli wiele projektów używa Fakes, może się zdarzyć, że zespoły Fakes z różnych wersji mogą się wzajemnie zastępować. Na przykład TestProject1 fakuje mscorlib.dll z platformy .NET Framework 2.0, a TestProject2 fakuje mscorlib.dll dla platformy .NET Framework 4, co w obu przypadkach dałoby zestaw mscorlib.Fakes.dll.

Aby uniknąć tego problemu, Fakes powinny automatycznie tworzyć nazwy zestawów Fakes wersji kwalifikowanych dla odwołań spoza projektu podczas dodawania plików .fakes. Nazwa zestawu Fakes z przypisanym numerem wersji zawiera/ma w sobie numer wersji, kiedy tworzysz nazwę 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ąć, zmieniając atrybut Wersja 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 fałszywek

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

Namespaces

  • Sufiks .fakes jest dodawany do przestrzeni nazw.

    Na przykład System.Fakes przestrzeń nazw zawiera typy shim przestrzeni nazw System.

  • Global.Fakes zawiera typ wstawki dla pustej przestrzeni nazw.

    Nazwy typów

  • Prefiks "shim" jest dodawany do nazwy typu, aby zbudować nazwę typu "shim".

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

  • Prefiks stubowy jest dodawany do nazwy typu w celu tworzenia nazwy typu stubowego.

    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.

Konwencje nazewnictwa dla właściwości delegata typu shim lub pól sztucznych delegata

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, Ofn jest dołączany, 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... Example Dołączona nazwa metody
Konstruktor .ctor Constructor
Konstruktor statyczny .cctor StaticConstructor
Akcesor z nazwą metody składającą się z dwóch części oddzielonych ciągiem "_" (na przykład akcesorów właściwości) kind_name (typowy przypadek, ale nie wymuszany przez ECMA) NameKind, gdzie obie części mają wielkie litery i zostały zamienione miejscami
Getter właściwości Prop PropGet
Setter właściwości Prop PropSet
Dodawanie 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 / Notatka

  • 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 występuje 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

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

Przestrzeń nazw, struktura zagnieżdżona i typy generyczne zostają usunięte.
Parametr wyjściowyout T TOut
Parametr odwołaniaref T TRef
Typ tablicyT[] TArray
Wielowymiarowy typ tablicyT[ , , ] T3
Typ wskaźnikaT* TPtr
Typ ogólnyT<R1, ...> TOfR1
Argument typu ogólnego!iC<TType> Ti
Argument ogólny!!i metodyM<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 spowodowałby nieprawidłowy token języka C#, jest zamieniany na znak "_" (podkreślenie).

  • Jeśli wynikowa nazwa koliduje z dowolnym członkiem typu deklarowanego, stosuje się schemat numeracji, który polega na dołączeniu dwucyfrowego licznika, zaczynając od 01.

Wykorzystanie Microsoft Fakes w ciągłej integracji

Generowanie Asemblacji Microsoft Fakes

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 / Notatka

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 wygenerowanego zestawu Fakes w swoim 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.