5

Ich versuche, mein CodedUI-Testgenerator-Plug-in in SpecFlow 1.9 hinzuzufügen. Ich versuche die neue Plugin-Registrierung zu verwenden, da die alte Art der Registrierung alle Arten von Problemen in unserer Lösung verursacht, da wir es vorziehen, den benutzerdefinierten Generator-Provider nicht in das Specflow-Installationsverzeichnis zu legen (was auf jedem Entwickler-Rechner anders ist) .Benutzerdefinierte SpecFlow TestGeneratorProvider-Registrierung verursacht NullReferenceException bei Testgenerierung

Ich begann mit dem Hinzufügen der neuen Specflow.CustomPlugin NuGet package zu einer .NET 4.0-Klassenbibliothek.

Basierend auf den Proben für den CodedUI Generator, pieced ich dies zusammen:

using TechTalk.SpecFlow.Infrastructure; 
[assembly: GeneratorPlugin(typeof(CodedUIGeneratorProvider.Generator.SpecFlowPlugin.CodedUIGeneratorPlugin))] 

namespace CodedUIGeneratorProvider.Generator.SpecFlowPlugin 
{ 
    using System.CodeDom; 

    using BoDi; 

    using TechTalk.SpecFlow.Generator; 
    using TechTalk.SpecFlow.Generator.Configuration; 
    using TechTalk.SpecFlow.Generator.Plugins; 
    using TechTalk.SpecFlow.Generator.UnitTestProvider; 
    using TechTalk.SpecFlow.UnitTestProvider; 
    using TechTalk.SpecFlow.Utils; 

    /// <summary> 
    /// The CodedUI generator plugin. 
    /// </summary> 
    public class CodedUIGeneratorPlugin : IGeneratorPlugin 
    { 
     /// <summary> 
     /// The register dependencies. 
     /// </summary> 
     /// <param name="container"> 
     /// The container. 
     /// </param> 
     public void RegisterDependencies(ObjectContainer container) 
     { 
     } 

     /// <summary> 
     /// The register customizations. 
     /// </summary> 
     /// <param name="container"> 
     /// The container. 
     /// </param> 
     /// <param name="generatorConfiguration"> 
     /// The generator configuration. 
     /// </param> 
     public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration) 
     { 
      container.RegisterTypeAs<CodedUIGeneratorProvider, IUnitTestGeneratorProvider>("default"); 
      container.RegisterTypeAs<MsTest2010RuntimeProvider, IUnitTestRuntimeProvider>("default"); 
     } 

     /// <summary> 
     /// The register configuration defaults. 
     /// </summary> 
     /// <param name="specFlowConfiguration"> 
     /// The spec flow configuration. 
     /// </param> 
     public void RegisterConfigurationDefaults(SpecFlowProjectConfiguration specFlowConfiguration) 
     { 
     } 
    } 

    /// <summary> 
    /// The CodedUI generator. 
    /// </summary> 
    public class CodedUIGeneratorProvider : MsTest2010GeneratorProvider 
    { 
     /// <summary> 
     /// Initializes a new instance of the <see cref="CodedUiGeneratorProvider"/> class. 
     /// </summary> 
     /// <param name="codeDomHelper"> 
     /// The code dom helper. 
     /// </param> 
     public CodedUIGeneratorProvider(CodeDomHelper codeDomHelper) 
      : base(codeDomHelper) 
     { 
     } 

     /// <summary> 
     /// The set test class. 
     /// </summary> 
     /// <param name="generationContext"> 
     /// The generation context. 
     /// </param> 
     /// <param name="featureTitle"> 
     /// The feature title. 
     /// </param> 
     /// <param name="featureDescription"> 
     /// The feature description. 
     /// </param> 
     public override void SetTestClass(TestClassGenerationContext generationContext, string featureTitle, string featureDescription) 
     { 
      base.SetTestClass(generationContext, featureTitle, featureDescription); 

      foreach (CodeAttributeDeclaration declaration in generationContext.TestClass.CustomAttributes) 
      { 
       if (declaration.Name == "Microsoft.VisualStudio.TestTools.UnitTesting.TestClassAttribute") 
       { 
        generationContext.TestClass.CustomAttributes.Remove(declaration); 
        break; 
       } 
      } 

      generationContext.TestClass.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference("Microsoft.VisualStudio.TestTools.UITesting.CodedUITestAttribute"))); 
     } 
    } 
} 

Und wenn man versucht, es wie folgt zu konfigurieren:

<specFlow> 
    <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config --> 
    <plugins> 
     <add name="CodedUIGeneratorProvider" path="." type="GeneratorAndRuntime"/> 
    </plugins> 
    <generator dependencies="CodedUIGeneratorProvider"/> 
    <runtime dependencies="CodedUIGeneratorProvider"/> 
    </specFlow> 

ich folgende Fehlermeldung:

Der Fehler wird innerhalb des SpecFlow-Konfigurationscodes, der Stapelverfolgung, verursacht wie folgt:

System.Configuration.dll!System.Configuration.ConfigurationProperty.ConvertFromString(string value) + 0x2a bytes 
System.Configuration.dll!System.Configuration.ConfigurationElement.DeserializePropertyValue(System.Configuration.ConfigurationProperty prop, System.Xml.XmlReader reader) + 0x36 bytes 
System.Configuration.dll!System.Configuration.ConfigurationElement.DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) + 0x221 bytes 
System.Configuration.dll!System.Configuration.ConfigurationElement.DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey) + 0x78e bytes 
System.Configuration.dll!System.Configuration.ConfigurationSection.DeserializeSection(System.Xml.XmlReader reader) + 0x3c bytes 
TechTalk.SpecFlow.dll!TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler.CreateFromXml(string xmlContent) + 0xb0 bytes 
TechTalk.SpecFlow.Generator.dll!TechTalk.SpecFlow.Generator.Configuration.GeneratorConfigurationProvider.LoadConfiguration(TechTalk.SpecFlow.Generator.Interfaces.SpecFlowConfigurationHolder configurationHolder, TechTalk.SpecFlow.Generator.Configuration.SpecFlowProjectConfiguration configuration) + 0x41 bytes 
TechTalk.SpecFlow.Vs2010Integration.dll!TechTalk.SpecFlow.Vs2010Integration.Generator.VsGeneratorInfoProvider.GenGeneratorConfig() + 0x52 bytes 
TechTalk.SpecFlow.Vs2010Integration.dll!TechTalk.SpecFlow.Vs2010Integration.Generator.VsGeneratorInfoProvider.GetGeneratorInfo() + 0x3a bytes 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.RemoteGeneratorServices.GetGeneratorInfo() Line 38 + 0x9 bytesC# 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.RemoteGeneratorServices.GetTestGeneratorFactoryForCreate() Line 43 + 0xa bytesC# 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.GeneratorServices.CreateTestGenerator() Line 24 + 0xa bytesC# 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.IdeSingleFileGenerator.GenerateCode(string inputFilePath, string inputFileContent, TechTalk.SpecFlow.IdeIntegration.Generator.GeneratorServices generatorServices, TechTalk.SpecFlow.Generator.Interfaces.ProjectSettings projectSettings) Line 38 + 0x29 bytesC# 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.IdeSingleFileGenerator.Generate(string inputFilePath, string inputFileContent, TechTalk.SpecFlow.IdeIntegration.Generator.GeneratorServices generatorServices, TechTalk.SpecFlow.Utils.CodeDomHelper codeDomHelper, TechTalk.SpecFlow.Generator.Interfaces.ProjectSettings projectSettings) Line 23 + 0x12 bytesC# 
TechTalk.SpecFlow.IdeIntegration.dll!TechTalk.SpecFlow.IdeIntegration.Generator.IdeSingleFileGenerator.GenerateFile(string inputFilePath, string outputFilePath, System.Func<TechTalk.SpecFlow.IdeIntegration.Generator.GeneratorServices> generatorServicesProvider, System.Func<string,string> inputFileContentProvider, System.Action<string,string> outputFileContentWriter) Line 92 + 0x13 bytesC# 
TechTalk.SpecFlow.Vs2010Integration.dll!TechTalk.SpecFlow.VsIntegration.SingleFileGenerator.SpecFlowSingleFileGeneratorBase.GenerateInternal(string inputFilePath, string inputFileContent, EnvDTE.Project project, string defaultNamespace, System.Action<TechTalk.SpecFlow.VsIntegration.SingleFileGenerator.SingleFileGeneratorError> onError, out string generatedContent) + 0x18e bytes 
TechTalk.SpecFlow.Vs2010Integration.dll!TechTalk.SpecFlow.VsIntegration.SingleFileGenerator.SingleFileGeneratorBase.Generate(string inputFilePath, string inputFileContents, string defaultNamespace, System.IntPtr[] rgbOutputFileContents, out uint pcbOutput, Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress generateProgress) + 0xc3 bytes 
[Native to Managed Transition] 

Welche Reflektor mich kann nur bedeuten, dass sagt TechTalk.SpecFlow.IdeIntegration.Generator.RemoteGeneratorServices.generatorInfoProvidernull ist.

Ich bin ratlos, wie das zu beheben ist. Es gibt sehr wenig Dokumentation, um das Problem zu lösen.

Die Frage:

Wenn ich diese Arbeit bekommen kann ich sehr zufrieden sein würde. alternativ würde ich gerne eine Möglichkeit sehen, den "alten Weg" zu konfigurieren, ohne Dateien in das SpecFlow-Installationsverzeichnis zu legen.

Antwort

1

Für Entwickler kommen hier mit SpecFlow 2.1.0 finden Sie im folgenden auf die CodedUIGeneratorProvider Klasse oben hinzufügen:

public void Initialize(GeneratorPluginEvents generatorPluginEvents, GeneratorPluginParameters generatorPluginParameters) 
    { 
     generatorPluginEvents.CustomizeDependencies += GeneratorPluginEvents_CustomizeDependencies; 
    } 

    private void GeneratorPluginEvents_CustomizeDependencies(object sender, CustomizeDependenciesEventArgs eventArgs) 
    { 
     eventArgs.ObjectContainer.RegisterTypeAs<CodedUIGeneratorProvider, IUnitTestGeneratorProvider>(); 
    } 

Die Schnittstelle der CustomPlugin Schnittstelle hat sich geändert, Es ist notwendig, an Anpassungsereignisse anzuknüpfen, um die Anpassung registrieren zu lassen.

Siehe https://github.com/techtalk/SpecFlow/wiki/Plugins

5

ich das Problem gefunden :)

Im Register Customizations Methode des Plugins, registriere keinen Namen verwenden, benutzen Sie einfach die RegisterTypeAs Methode:

public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration) 
{ 
    container.RegisterTypeAs<CodedUIGeneratorProvider, IUnitTestGeneratorProvider>(); 
} 

Dann die Config sieht sehr einfach , wie folgt aus:

<specFlow> 
    <!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config --> 
    <plugins> 
    <add name="CodedUIGeneratorProvider" path="." type="Generator"/> 
    </plugins> 
</specFlow> 

diese Weise können Sie das Plug-Montage fallen kann im Projektverzeichnis (das *.SpecflowPlugin.dll benannt werden muss) oder eine relative p verwenden ath aus dem Projektverzeichnis und setzen Sie es in der path=".\Lib" Eigenschaft der plugins\add Artikel.

Weitere Informationen finden Sie unter: http://blog.jessehouwing.nl/2013/04/creating-custom-unit-test-generator.html