jes*_*ing 5 plugins configuration-files nullreferenceexception specflow
我正在尝试在SpecFlow 1.9中添加我的CodedUI测试生成器插件.我正在尝试使用新的插件注册,因为旧的注册类型会在我们的解决方案中引起各种问题,因为我们不希望将自定义Generator Provider放在Specflow安装目录中(在每个开发人员计算机上都不同) .
我开始将新的Specflow.CustomPlugin NuGet包添加到.NET 4.0类库中.
基于CodedUI Generator的示例,我将它拼凑在一起:
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")));
}
}
}
Run Code Online (Sandbox Code Playgroud)
在尝试配置时如下:
<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>
Run Code Online (Sandbox Code Playgroud)
我收到以下错误消息:
错误生成错误:SpecFlow配置错误 - >无法解析属性"dependencies"的值.错误是:对象引用未设置为对象的实例.
错误是在SpecFlow配置代码内部引起的,堆栈跟踪如下:
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]
Run Code Online (Sandbox Code Playgroud)
其反射告诉我,只能说明TechTalk.SpecFlow.IdeIntegration.Generator.RemoteGeneratorServices.generatorInfoProvider是null.
我对如何解决这个问题感到茫然.解决此问题的文档很少.
如果我能让这个工作,我会非常高兴.我很乐意看到一种配置'旧方式'的方法,而不必将文件放在SpecFlow安装目录中.
我找到了问题:)
在插件的Register Customizations方法中,不要使用名称注册,只需使用以下RegisterTypeAs方法:
public void RegisterCustomizations(ObjectContainer container, SpecFlowProjectConfiguration generatorConfiguration)
{
container.RegisterTypeAs<CodedUIGeneratorProvider, IUnitTestGeneratorProvider>();
}
Run Code Online (Sandbox Code Playgroud)
然后配置看起来很简单,像这样:
<specFlow>
<!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->
<plugins>
<add name="CodedUIGeneratorProvider" path="." type="Generator"/>
</plugins>
</specFlow>
Run Code Online (Sandbox Code Playgroud)
这样,您可以将插件程序集(必须命名*.SpecflowPlugin.dll)放在项目目录中,或者使用项目目录中的相对路径并将其设置在项目的path=".\Lib"属性中plugins\add.
有关更多信息,请参阅:https://jessehouwing.net/specflow-custom-unit-test-generator/
对于使用 SpecFlow 2.1.0 的开发人员,请将以下内容添加到上面的 CodedUIGeneratorProvider 类中:
public void Initialize(GeneratorPluginEvents generatorPluginEvents, GeneratorPluginParameters generatorPluginParameters)
{
generatorPluginEvents.CustomizeDependencies += GeneratorPluginEvents_CustomizeDependencies;
}
private void GeneratorPluginEvents_CustomizeDependencies(object sender, CustomizeDependenciesEventArgs eventArgs)
{
eventArgs.ObjectContainer.RegisterTypeAs<CodedUIGeneratorProvider, IUnitTestGeneratorProvider>();
}
Run Code Online (Sandbox Code Playgroud)
CustomPlugin 接口的界面已更改,因此需要连接到自定义事件才能注册自定义。
请参阅https://github.com/techtalk/SpecFlow/wiki/Plugins