Geração de código, compilação e convenções de nomenclatura no Microsoft Fakes
Este tópico discute as opções e os problemas na geração e compilação de código do Fakes, e descreve as convenções de nomeação para os parâmetros, membros, e os tipos gerados do Fakes.
Requisitos
- Visual Studio Ultimate •
Neste tópico
Geração de código e compilação
- Configurando a geração de código de stub • Filtragem de tipo • Classes concretas pelo stub e métodos virtuais • Tipos internos • Otimizando tempo de compilação • Evitando a discordância do nome do assembly
Convenções de nomeação de fakes
- Convenções de nomenclatura corretivas de tipo e o tipo de stub • Convenções de nomenclatura corretivas de propriedade de representante ou o campo de representante de stub • Convenções de nomenclatura do tipo de parâmetro • Regras recursivas
Recursos externos
- Orientação
Geração de código e compilação
Configurando a geração de código de stub
A geração de tipos de stub é configurada em um arquivo XML que tem a extensão de arquivo .fakes.A estrutura de falsificação integra-se no processo de compilação com as tarefas personalizadas do MSBuild e detecta esses arquivos em tempo de compilação.O gerador de código de falsificação compila os tipos de stub em um assembly e adiciona a referência ao projeto.
O exemplo a seguir ilustra os tipos de stub definidos em FileSystem.dll:
<Fakes xmlns="https://schemas.microsoft.com/fakes/2011/">
<Assembly Name="FileSystem"/>
</Fakes>
Filtragem de tipo
Filtros podem ser definidos no arquivo .fakes para restringir que tipos devem ser arrancados.Você pode adicionar um número ilimitado de elementos para limpar, adicionar e remover no elemento StubGeneration para criar a lista de tipos selecionados.
Por exemplo, esse arquivo .fakes gera stub para tipos nos namespaces System and System.IO, mas exclui qualquer tipo que contém “Identificador” no sistema:
<Fakes xmlns="https://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>
As cadeias de caracteres usam uma gramática simples para definir como a correspondência deve ser feita:
Por padrão, filtros diferenciam maiúsculas de minúsculas; filtros executam uma correspondência de subcadeias de caracteres:
el corresponde a “Olá”
Adicionar ! ao final de filtro fará uma correspondência precisa que diferencia maiúsculas de minúsculas:
el! não corresponde a "olá"
hello! corresponde a “Olá”
Adicionar * ao final do filtro fará coincidir com o prefixo da cadeia de caracteres:
el* não corresponde a "olá"
he* corresponde a “Olá”
Vários filtros em uma lista separada por ponto-e-vírgula- são combinados como uma disjunção:
el;wo corresponde a “olá” e “mundo”
Classes concretas pelo stub e métodos virtuais
Por padrão, os tipos de stub são gerados para todas as classes vedadas.É possível restringir os tipos de stub para classes abstratas por meio do arquivo de configuração .fakes:
<Fakes xmlns="https://schemas.microsoft.com/fakes/2011/">
<Assembly Name="mscorlib" />
<!-- user code -->
<StubGeneration>
<Types>
<Clear />
<Add AbstractClasses="true"/>
</Types>
</StubGeneration>
<!-- /user code -->
</Fakes>
Tipos internos
O gerador de código de falsificação gerará tipos shim e stub para tipos que são visíveis para o assembly gerado de falsificação.Para tornar os tipos internos de um assembly calçado visíveis ao Fakes e ao seu assembly de teste, adicione os atributos de InternalsVisibleToAttribute ao código de assembly calçado que fornece visibilidade ao assembly gerado do Fakes e ao assembly de teste.Veja um exemplo:
// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes")]
[assembly: InternalsVisibleTo("FileSystem.Tests")]
Tipos internas em assemblies fortemente nomeados
Se o assembly calçado tiver um nome forte e você quiser acessar tipos internos do assembly:
O assembly de teste e o assembly de falsificação devem ser fortemente nomeados.
Você deve adicionar as chaves públicas de teste e falsificar o assembly para atributos de InternalsVisibleToAttribute em assemblies convertidos.Veja qual seria a aparência de nossos atributos de exemplo no código calçado do assembly quando o assembly calçado tem um nome forte:
// FileSystem\AssemblyInfo.cs [assembly: InternalsVisibleTo("FileSystem.Fakes", PublicKey=<Fakes_assembly_public_key>)] [assembly: InternalsVisibleTo("FileSystem.Tests", PublicKey=<Test_assembly_public_key>)]
Se o assembly calçado tiver um nome forte, a estrutura de elementos fictícios assinará automaticamente com força o assembly de elementos fictícios gerados.Você precisa do sinal de alta segurança no assembly de teste.Consulte Criando e usando assemblies de nomes fortes.
A estrutura de falsificação usa a mesma chave para assinar os assemblies gerados, portanto você pode usar esse trecho de código como um ponto de partida para adicionar o atributo de InternalsVisibleTo para o assembly de falsificação ao seu código de assembly corrigido.
[assembly: InternalsVisibleTo("FileSystem.Fakes, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e92decb949446f688ab9f6973436c535bf50acd1fd580495aae3f875aa4e4f663ca77908c63b7f0996977cb98fcfdb35e05aa2c842002703cad835473caac5ef14107e3a7fae01120a96558785f48319f66daabc862872b2c53f5ac11fa335c0165e202b4c011334c7bc8f4c4e570cf255190f4e3e2cbc9137ca57cb687947bc")]
Você pode especificar uma chave pública diferente para assemblies falsos, como uma chave que você criou para o assembly calçado, especificando o caminho completo do arquivo de .snk que contém a chave alternativa como o valor tributo KeyFile no elemento do arquivo Fakes\Compilation do arquivo .fakes.Por exemplo:
<-- FileSystem.Fakes.fakes -->
<Fakes ...>
<Compilation KeyFile="full_path_to_the_alternate_snk_file" />
</Fakes>
Em seguida, você precisa usar a chave pública do arquivo alternativo .snk como o segundo parâmetro do atributo InternalVisibleTo para o assembly do Fakes no código de assembly calçado:
// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes",
PublicKey=<Alternate_public_key>)]
[assembly: InternalsVisibleTo("FileSystem.Tests",
PublicKey=<Test_assembly_public_key>)]
No exemplo anterior, os valores Alternate_public_key e Test_assembly_public_key podem ser iguais.
Otimizando tempo de compilação
A compilação os assemblies de falsificação pode aumentar significativamente o momento da compilação.Você pode minimizar o tempo de compilação produzindo os assemblies de falsificação para os assemblies do .NET System e assemblies de terceiros em um projeto centralizado separado.Como esses conjuntos raramente alteram-se no seu computador, você pode reutilizar os assemblies de falsificação gerados em outros projetos.
Em seus projetos de teste de unidade, você pode simplesmente executar uma referência para os assemblies de elementos fictícios compilados que são colocados no FakesAssemblies na pasta do projeto.
Crie uma nova Biblioteca de Classe com a versão de tempo de execução do. NET que corresponde a seus projetos de teste.Vamos chamá-la de Fakes.Prebuild.Remova o arquivo class1.cs do projeto, não necessário.
Adicionar referência a todo Sistema e assemblies de terceiros que você precisa para falsificação.
Adicione um arquivo .fakes para cada um dos assemblies e compile-os.
No seu projeto de teste
Verifique se você tem uma referência para a DLL em tempo de execução do Fakes:
C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies\Microsoft.QualityTools.Testing.Fakes.dll
Em relação a cada assembly para os quais você criou elemento fictícios, adicione uma referência ao arquivo DLL correspondente na pasta Fakes.Prebuild \ FakesAssemblies de seu projeto.
Evitar a discordância de nome do assembly
Em um ambiente do Team Build, todas as saídas de compilação são mescladas em um único diretório.No caso de vários projetos usando o Fakes, pode acontecer que os assemblies do Fakes de versão diferente substituam uns aos outros.For example, mscorlib.dll de elementos fictícios TestProject1 do .NET Framework 2.0 e mscorlib.dll de elementos fictícios TestProject2 para o .NET Framework 4 poderiam ceder a um assembly de elementos fictícios mscorlib.Fakes.dll Fakes assembly.
Para evitar esse problema, o Fakes deve criar automaticamente nomes de assembly de versão qualificada do Fakes para as referências não pertencentes ao projeto ao adicionar arquivos .fakes.Um nome do assembly de elementos fictícios qualificados pela versão insere um número de versão quando você o cria:
Dado um assembly MyAssembly e uma versão 1.2.3.4, o nome do assembly de elementos fictícios é MyAssembly.1.2.3.4.Fakes.
Você pode modificar ou remover essa versão editando o atributo da versão do elemento assembly no arquivo .fakes:
attribute of the Assembly element in the .fakes:
<Fakes ...>
<Assembly Name="MyAssembly" Version="1.2.3.4" />
...
</Fakes>
Convenções de nomeação de fakes
O tipo corretivo e o stub tipo convenções de nomenclatura
Namespaces
Sufixos falsos são adicionados ao namespace.
Por exemplo, o namespace System.Fakes contém os tipos corretivos de namespace do sistema.
Global.Fakes contém o tipo corretivo de namespace vazio.
Nomes de tipos
O prefixo corretivo é adicionado ao nome do tipo para compilar o nome corretivo de tipo.
Por exemplo, ShimExample é o tipo corretivo do tipo Exemplo.
O prefixo stub é adicionado ao nome do tipo para compilar o nome corretivo de stub.
Por exemplo, StubIExample é o tipo de stub do tipo IExemple.
Argumentos de tipo e estruturas aninhadas de tipo
Os argumentos de tipo genérico são copiados.
A estrutura de tipos aninhado é copiada para tipos corretivos.
Convenções de nomeação corretivas da propriedade do representante ou do campo do representante
Regras básicas para a nomeação de campo a partir de um nome vazio:
O nome do método é acrescentado.
Se o nome do método é uma implementação explícita de interface, os pontos são removidos.
Se o método for genérico, Ofn será acrescentado onde n for o número de argumentos genéricos do método.
Nomes especiais de método como por exemplo, o getter ou setters de propriedade tratados, como descrito na tabela a seguir.
Se o método é… |
Exemplo |
Nome do método anexado |
---|---|---|
Um construtor |
.ctor |
Constructor |
Um construtorestático |
.cctor |
StaticConstructor |
Um acessador com o nome do método composto de duas partes separadas por “_” (como getters de propriedade) |
kind_name (caso comum, mas não imposto por ECMA) |
NameKind, onde ambas as partes tiveram a primeira letra colocada em maiúscula e alternadas |
Getter da propriedade Prop |
PropGet |
|
Setter da propriedade Prop |
PropSet |
|
Adicionador de evento |
Add |
|
Removedor de evento |
Remove |
|
Um operador composto de duas partes |
op_name |
NameOp |
Por exemplo: + operador |
op_Add |
AddOp |
Para obter um operador de conversão, o tipo de retorno é acrescentado. |
T op_Implicit |
ImplicitOpT |
Notas
Getters e setters de indexadores são tratados de forma semelhante à propriedade.O nome padrão de um indexador é Item.
Os nomes deTipo de parâmetro são transformados e concatenados.
Tipo de retorno é ignorado, a menos que haja uma ambiguidade de sobrecarga.Se for esse o caso, o tipo de retorno será acrescentado ao final do nome
Convenções de nomeação do tipo de parâmetro
Determinado |
A cadeia de caracteres anexada é… |
---|---|
Um tipoT |
T O namespace, a estrutura aninhada, e os TICs genéricos são ignorados. |
Um parâmetro outout T |
TOut |
Um parâmetro de referência ref T |
TRef |
Um tipo de matrizT[] |
TArray |
Um tipo de matriz multidimensionalT[ , , ] |
T3 |
Um tipo de ponteiro T* |
TPtr |
Um tipo genéricoT<R1, …> |
TOfR1 |
Um argumento de tipo genérico!i do tipo C<TType> |
Ti |
Um argumento do método genérico!!i do método M<MMethod> |
Mi |
Um tipo aninhadoN.T |
N é acrescentado, então T |
Regras recursivas
As seguintes regras são aplicadas recursivamente:
Como as falsificação usam o C# para gerar assemblies de falsificação, qualquer caractere que produz um token inválido de C# escapa para “_” (sublinhado).
Se um nome resultante entrar em conflito com qualquer membro do tipo declarativo, um esquema de numeração será usado ao anexar um contador de dois dígitos, começando com 01.