2008-12-12 7 views
6

J'essaie d'obtenir une liste de tous les ensembles de tests unitaires sous la racine de mon projet. Je peux le faire comme suit:Normaliser une liste d'éléments dans MSBuild

<CreateItem Include="**\bin\**\*.UnitTest.*.dll"> 
    <Output TaskParameter="Include" ItemName="Items"/> 
</CreateItem> 

Cependant, cela trouver les mêmes DLL plusieurs fois depuis qu'ils existent dans plusieurs sous-répertoires. Existe-t-il un moyen facile pour moi de normaliser en fonction des métadonnées d'éléments (c'est-à-dire le nom et l'extension du fichier) afin d'obtenir une liste de DLL de test unitaires uniques? Ou dois-je recourir à l'écriture de ma propre tâche?

Répondre

4

Le MSBuild Extension Pack contient la tâche MSBuildHelper, supportant la commande RemoveDuplicateFiles.

<CreateItem Include="**\bin\**\*.UnitTest.*.dll"> 
    <Output TaskParameter="Include" ItemName="Items"/> 
</CreateItem> 
<MSBuild.ExtensionPack.Framework.MsBuildHelper TaskAction="RemoveDuplicateFiles" InputItems1="@(Items)"> 
    <Output TaskParameter="OutputItems" ItemName="Items"/> 
</MSBuild.ExtensionPack.Framework.MsBuildHelper> 
+0

Sons utiles - merci. Je vais essayer la prochaine fois que j'en ai besoin. –

2

J'ai fait une bonne recherche en ligne et je n'ai trouvé aucun moyen de le faire. Si quelqu'un connaît un mode intégré propre alors s'il vous plaît faites le moi savoir. En attendant, j'ai écrit une tâche simple pour faire le travail. L'utilisation ressemble à ceci:

<NormalizeByMetadata Items="@(ItemsToNormalize)" MetadataName="Filename"> 
    <Output TaskParameter="NormalizedItems" ItemName="MyNormalizedItems"/> 
</NormalizeByMetadata> 

Une fois la tâche ci-dessus a exécuté, MyNormalizedItems contiendra uniquement les articles de ItemsToNormalize qui ont une valeur unique pour les Filename métadonnées. Si deux ou plusieurs éléments ont la même valeur pour leurs métadonnées Filename, la première correspondance sera incluse dans la sortie.

Le code de la tâche MSBuild est:

public class NormalizeByMetadata : Task 
{ 
    [Required] 
    public ITaskItem[] Items 
    { 
     get; 
     set; 
    } 

    [Required] 
    public string MetadataName 
    { 
     get; 
     set; 
    } 

    [Output] 
    public ITaskItem[] NormalizedItems 
    { 
     get; 
     private set; 
    } 

    public override bool Execute() 
    { 
     NormalizedItems = Items.Distinct(new ItemEqualityComparer(MetadataName)).ToArray(); 
     return true; 
    } 

    private sealed class ItemEqualityComparer : IEqualityComparer<ITaskItem> 
    { 
     private readonly string _metadataName; 

     public ItemEqualityComparer(string metadataName) 
     { 
      Debug.Assert(metadataName != null); 
      _metadataName = metadataName; 
     } 

     public bool Equals(ITaskItem x, ITaskItem y) 
     { 
      if (x == null || y == null) 
      { 
       return x == y; 
      } 

      var xMetadata = x.GetMetadata(_metadataName); 
      var yMetadata = y.GetMetadata(_metadataName); 
      return string.Equals(xMetadata, yMetadata); 
     } 

     public int GetHashCode(ITaskItem obj) 
     { 
      if (obj == null) 
      { 
       return 0; 
      } 

      var objMetadata = obj.GetMetadata(_metadataName); 
      return objMetadata.GetHashCode(); 
     } 
    } 
} 
+0

Comment créer un test unitaire pour la tâche NormalizeByMetadata? – Kiquenet

4

Même si cela est vieux, je ne pourrais jamais obtenir la solution Thomas à moi-même travailler, mais j'ai trouvé une sorte de solution de contournement en utilisant uniquement des commandes intégrées avec v4.0 de msbuild:

<ItemGroup> 
    <TestAssemblies Include="$(SolutionRoot)\**\bin\*.Tests.dll" /> 
    <TestItems Include="%(TestAssemblies.FileName)%(TestAssemblies.Extension)"> 
     <ItemPath>%(TestAssemblies.Identity)</ItemPath> 
    </TestItems> 
    <DistinctTestItems Include="@(TestItems->Distinct())"></DistinctTestItems> 
</ItemGroup> 
<Message Text="%(DistinctTestItems.ItemPath)" Importance="high" />