我最近(在上周)开始了一个实验,其中我尝试在我正在使用TDD原理的项目中编写新功能.在过去,我们的方法是一种适度敏捷的方法,但没有严格的严谨性.当方便时,单元测试就在这里和那里进行.全面测试覆盖的主要障碍是我们的应用程序具有复杂的依赖关系网.我选择了一个方便隔离的功能来尝试我的实验; 细节并不重要,可能具有商业敏感性,足以说这是一个简单的优化问题.
到目前为止,我发现:
那么问题是"有没有人建议减少上述问题的影响?".我毫不怀疑,嘲弄框架将是有利的; 但是目前我已经在努力尝试一些似乎只产生漫无边际码的东西.
编辑#1:
谢谢大家的考虑答案.我承认我在几个星期五晚上的啤酒之后写了我的问题,所以在某些地方它是模糊的,并没有真正表达我真正想要的情绪.我想强调一点,我确实喜欢 TDD的哲学,并且发现它适度成功,但由于我列出的原因也令人惊讶.我有机会睡觉,并在下周用新鲜的眼睛再次看问题,所以也许我可以通过混乱来解决我的问题.然而,他们都不是非先发者.
让我更担心的是,一些团队成员拒绝尝试任何你称之为"技术"的东西,而不是"完成它".我担心,残留的外观将被视为反对该过程的黑色标记,而不是证明它需要完全(即使用模拟框架和强烈的DI)以获得最佳结果.
RE"TDD不一定意味着测试优先":( womp,btreat)
我在这个问题上发现的每一篇文章中的"黄金法则"都是"红色,绿色,重构".那是:
我很好奇人们如何在不遵循最初编写的TDD核心原则的情况下进行测试驱动开发.我的同事称中途住宅(或根据您的观点采用不同且同样有效的方法)"测试验证开发".在这种情况下,我认为创造一个新术语 - 或者可能将其从其他人手中夺走并为此获得信誉 - 是有用的.
用于测试数据的RE DSL :( Michael Venable)
我很高兴你这么说.我确实看到一般表单在整个项目范围内越来越有用,因为所讨论的应用程序维护了一个非常复杂的对象图,通常,测试它意味着运行应用程序并在GUI中尝试.(由于上面的商业敏感性原因,不会将游戏放弃,但它基本上与有向图上的各种指标的优化有关.但是,涉及许多警告和用户可配置的小部件.)
能够以编程方式设置有意义的测试用例将有助于各种情况,可能不限于单元测试.
RE God Objects:
我觉得这样,因为一个班级似乎占据了大部分功能集.也许这很好,而且它确实很重要,但它引起了一些人的注意,因为它看起来就像那些没有沿着这些线路开发的旧代码,并且似乎违反了SRP.我认为不可避免的是,某些类主要用作众多不同封装功能之间的接缝,而其他类只能接缝.如果它会是这样的话,我想我需要做的是从这个明显的上帝对象中尽可能多地清除逻辑,并将其行为重新作为所有分解部分之间的连接点.
(对于主持人:我已将我对帖子的回复添加到此处,因为评论字段不够长,无法包含我想要的详细信息.)
编辑#2(大约五个月后):
好吧,我觉得在仔细考虑问题一段时间之后更新一些想法可能会更好.
最后我最终放弃了TDD方法,我很遗憾地说.但是,我觉得有一些具体和合理的理由,我很乐意在下次有机会时继续使用它.
TDD的无懈可击的重构心态的结果是,当我简单地看一下我的代码时,领导开发者宣称绝大部分都是毫无意义的并且需要去做,我并不感到非常沮丧.虽然不得不抛弃大量艰苦的工作而感到遗憾,但我确实看到了他的意思.
出现这种情况是因为我从字面上理解了"代码到接口"的规则,但继续编写试图代表现实的类.很久以前我第一次发表声明:
类不应该试图代表现实.对象模型应该只尝试解决手头的问题.
...我从那以后经常重复; 对我自己和任何会倾听的人.
这种行为的结果是执行函数的类的对象模型,以及重复类功能的镜像接口集.有了这个指向我,经过一段短暂但强烈的阻力之后,看到了光线,没有任何问题删除大部分.
这并不意味着我相信"接口的代码"是无聊的.它的意思是,当接口代表真实的业务功能时,编码到接口主要是有价值的,而不是看起来像现实生活的微缩副本的某些想象的完美对象模型的属性,但不考虑它的唯一含义生活要回答你最初提出的问题.TDD的优势在于它不能生产这样的模型,除非偶然.因为它首先提出问题并且只关心得到答案,所以不涉及你的自我和系统的先验知识.
我现在正在散步,所以我最好完成这个,并且说我很想再次尝试TDD,但是对可用的工具和策略有更好的概述,并会尽我所能来决定如何我想在跳进去之前去做.也许我应该将这个华夫饼干移植到它所属的博客上,一旦我有更多的话要说.
我(今天)第一次尝试过SpecFlow.我正在玩VS2010 Pro中创建一个新的类库并添加一个SpecFlow功能定义文件.
事实上,集成似乎没有正常工作,具有各种不同的错误.我选择了MsTest作为测试运行器,因为我不能打扰调用NUnit(我想长期使用NUnit,但目前我只想让一些BDD代码工作).然而,生成的代码文件继续引用NUnit - 这显然是错误的,因为我刚刚告诉SpecFlow使用MsTest运行.我已经完成了我能想到的再次调用代码生成的所有内容,包括使用工具>选项> SpecFlow中选择的MsTest选项创建一个全新的类库项目.
如果我将测试运行器字段设置为"自动"并右键单击功能文件,然后选择"运行SpecFlow方案",则会收到错误消息"无法找到匹配的测试运行器".
如果我不是测试运行字段更改为MSTest的,我得到做同样的事情不同的错误消息 - "未设置为一个对象的实例对象参考".我对此并不感到惊讶,因为它仍在尝试运行NUnit测试,即使我已明确要求MsTest,但显然它不应该nullref并将其呈现给用户.
我究竟做错了什么?文档没有帮助,据我所知,没有FAQ.
编辑#1:我已经确定App.Config使用该字段提供了我正在寻找的实际设置<unitTestProvider name="MsTest" />.我可以看到发生了什么 - Visual Studio选项菜单中的字段似乎没有修改您当前正在处理的项目.事实是,这使得它看起来像该领域根本不做任何事情.我现在说服SpecFlow生成MsTest类并使用MSTest运行程序运行.
所以现在问题变成了一个稍微不同的问题:工具>选项> SpecFlow>测试运行工具字段有什么(如果有的话)?
问题是听起来的.无论我多么努力,多久我都会尝试理解WPF,我觉得我正撞在墙上.我喜欢Winforms,一切都很有意义.
作为一个例子,我正在尝试编写一个简单的应用程序,它允许我布置一堆二维路径(由折线表示)并拖动它们的顶点,并使顶点信息与演示者同步(即,我想,一个ViewModel)
因此问题是:
IExtendedObjectPresenter作为数据源的实例;IExtendedObject,为每个绘制一条折线IExtendedObject;IExtendedObject.Points,将折线顶点放置在指定的坐标处.IDE在这里完全没有给我任何帮助.XAML中可用的许多属性对我来说都没有意义.因为似乎隐含地做了很多,所以没有明显的地方可以告诉窗户该做什么.
在我定期并告知RTFM之前,我想再次强调我已经多次研究过WPF的基本概念.我对它的了解不比我第一次发布时所做的更多.它似乎完全无法穿透.给出一种行为类型的示例并不以任何方式适用于稍微不同的行为,因此您将回到原点.我希望重复和有针对性的例子可能会在某些时候打开我的脑海.
我有一个BizTalk WCF自定义接收位置,我已添加自定义行为:
public class SasTokenProviderEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(sharedAccessSecretName, sharedAccessKey);
bindingParameters.Add(new TransportClientEndpointBehavior { TokenProvider = tokenProvider });
}
}
}
Run Code Online (Sandbox Code Playgroud)
为简洁起见,省略了参数设置代码
这是根据https://code.msdn.microsoft.com/How-to-integrate-BizTalk-07fada58#content中的示例改编的- 该作者在BizTalk社区中受到广泛尊重,此类代码已被使用好几年了.我正在做的就是调整他使用的方法,这被证明有效,可以替换不同的TokenProvider.
我可以通过调试看到此代码运行并且具有正确参数的TransportClientEndpointBehavior被添加到通道中.但是,当BizTalk接收位置轮询Service Bus时,我在事件日志中看到以下内容:
适配器"WCF-Custom"引发了错误消息.详细信息"System.UnauthorizedAccessException:40102:缺少授权令牌,资源:sb:// [namespace] .servicebus.windows.net/[queue] .TrackingId:452c2534-d3e6-400f-874f-09be324e9e11_G27,SystemTracker:[namespace]. servicebus.windows.net:[queue],时间戳:12/1/2016 11:38:56 AM ---> System.ServiceModel.FaultException:40102:缺少授权令牌,资源:sb:// [namespace] .servicebus .windows.net/[queue] .TrackingId:452c2534-d3e6-400f-874f-09be324e9e11_G27,SystemTracker:[namespace] .servicebus.windows.net:[queue],时间戳:12/1/2016 11:38:56 AM
我看不出Azure Service Bus端点会返回此错误消息的任何原因,因为没有使用令牌提供程序.为什么频道会忽略TokenProvider,我必须做什么才能正确传递令牌?
编辑:
我已经检查了有问题的端口的原始WCF消息流量以及使用SB-Messaging适配器的流量,该适配器按预期工作.区别在于SB-Messaging适配器的消息包含SOAP标头,如:
<Authorization xmlns="http://schemas.microsoft.com/servicebus/2010/08/protocol/">SharedAccessSignature sr=[really long encoded string]</Authorization>而我的自定义绑定端口的消息没有.所以问题是缺少授权SOAP标头; 但问题仍然存在 - 为什么通道不添加此标题?
编辑#2:
我已经反编译了Microsoft.ServiceBus.dll,我相信我已经找到了实际创建WCF消息的类,Microsoft.ServiceBus.Messaging.Sbmp.SbmpMessageCreator.它有这个方法:
private Message CreateWcfMessageInternal(string action, object body, bool …Run Code Online (Sandbox Code Playgroud) 我的雇主在我们所有的.Net生产软件上使用Dotfuscator.因此,我们绝对禁止使用任何内置的数据绑定或任何反映属性/函数名称的东西 - 因为dotfuscator会更改它们,因此任何立即绑定并且不可逆转地中断.
我一直在脑子里推翻这个逻辑,它开始受到伤害.还有必须要避免这种僵局的一种方式,它太广泛而根本的问题不具有已逃脱了我们一个明显的解决方案.
那么,如何用混淆反思?有什么诀窍?据推测,必须有足够智能的商业混淆器来解决问题.我们的版本有哪些选择?
我正在尝试使用Dynamics CRM Online 2016和BizTalk 2013 R2实现服务器到服务器的集成.我使用WebHttpBinding来调用CRM Web API,这需要一个作为http头提供的持有者令牌:
Authorization: Bearer [base64string]
我编写了一个客户端消息检查器,它使用ADAL调用Azure AD来获取访问令牌.这是通过客户端断言证书保护的,该证书已分配给AD租户中的已注册应用程序:
var token = context.AcquireTokenAsync(this.ResourceUri, assertionCert).Result;
ResourceUri 是 https://[myorganisation].crm4.dynamics.comassertionCert 是使用应用程序注册应用程序ID和机器证书存储区中的x509证书创建的ClientAssertionCertificate,该证书存储区作为KeyCredential注册到应用程序这"有用",因为它返回一个令牌,我可以解码这个令牌来检查声明 - 其中有相当数量,我无法确定这是否是CRM要求的一组声明.
AD应用程序注册配置了对CRM实例的委派权限.
我已将CRM本地用户中的应用程序ID设置为应用程序注册的应用程序ID.
在调用webAPI并提供此令牌时,CRM会响应401 unauthorized.
我在powershell脚本和PostMan中重复了相同的过程,所有这些过程似乎都表现出相同的行为.
我还应该做些什么来让CRM接受我的访问令牌?
编辑#1:尝试硬编码权限URI https://login.windows.net/[my-tenant-id]/oauth2/token而不是动态获取权限的内容AuthenticationParameters- 这是相同的值,除了以/ authorization而不是/ token结尾.这是零差异.
编辑#2:我正在使用的管理员向我指出,我期望使用的应用程序用户没有分配用户角色 - 这已被修改为具有允许API访问的角色,但这也没有区别.
编辑#3:oauth2AllowImplicitFlow在应用注册的清单中设置为true.这没有任何区别.
编辑#4:通过创建新的应用注册取得了一些进展,这次是作为Native应用而不是Web应用.我设法使用客户端密钥获取令牌,这被接受了 - 但是在将证书分配给应用程序并像以前一样呈现ClientAssertionCertificate时,我从权威机构获得响应:
Error validating credentials. AADSTS50012: Client is public so a client_assertion' should not be presented.
为什么?"客户公开"是什么意思?只是工作!
我在理解如何在LINQ中执行某些操作时遇到问题.
我有一个链表,对象的类型无关紧要.重要的是我想Where()根据当前对象与列表中下一个对象之间的关系做一些事情.
为什么我不能这样做:
linkedlist.Where(n=>a_function(n.Value, n.Next.Value))?
如果可能的话,这样做的语法是什么?类型推断系统似乎坚持我想要lambda参数,而T不是LinkedListNode<T>.
假设我已经定义了一个度量单位:
[<Measure>] type Blob
我想要一个类型,以每秒Blobs的值作为构造函数参数:
type Something(flowRate:double<Blob/s>) = ...
F#对此抛出一个摇摆不定 - "double不期望任何类型的参数,但这里给出了1个类型的参数"
我理解这个消息.我曾经认为我试图做的很明显,但我承认语法可能是错误的.问题是,我如何在代码中表达这种关系?
我在.net 4中尝试使用winforms应用程序(基本上是草图,我使用它有点像kata,但没有那么严格或具体)的Ninject.
要创建主窗体,我正在执行以下操作:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
[...]
IKernel kernel = BuildKernel();
Application.Run(kernel.Get<frmMain>());
}
static IKernel BuildKernel()
{
var modules = new INinjectModule[]
{
[..modules]
};
return new StandardKernel(modules);
}
}
Run Code Online (Sandbox Code Playgroud)
精细.这将创建一个主窗体并很好地显示它,将适当的接口实现传递给注入的构造函数.
怎么办?我的应用程序是一个MDI,将有几个子窗口用于操作应用程序模型.我不再有对内核的引用了,所以我应该如何处理Get()这些形式?显而易见的答案是"我将内核传递给表单",但这是一个非常混乱的策略,我确信这不符合DI的理念.
我将在此指出Ninject 2的文档很糟糕.我能找到的一切都重复了基本的例子,而没有真正解释使用Ninject的DI如何让事情变得更容易.给出的示例标准并不复杂,不足以使编码和创建模块和绑定的麻烦变得有价值.
编辑#1:
在研究了Sam Holder友情提供的链接后,我正在尝试"组合根"方法.我的架构现在强制它使用的所有表单从CompositedForm构造函数语义派生,因此:
[Inject]
public CompositingForm(ICompositionRoot CompositionRoot)
{
InitializeComponent();
this.CompositionRoot = CompositionRoot;
}
public readonly ICompositionRoot CompositionRoot;
public CompositingForm() : …Run Code Online (Sandbox Code Playgroud) 我在家里玩 Ninject 一个简单的测试平台项目,只是想看看我能用它做什么。作为起点,我正在为某些服务构建一个控制台运行程序,它接受各种参数,并根据它所输入的内容,使用为流畅的界面提供的相同方法来配置要运行的模型。
举个例子,假设我有一个详细的开关,/o. /o可以作为/o:quiet, /o:normal, 或 传递/o:verbose。各种选项是不言自明的。
为了满足这个论点,我想附上各种实现ILogger- quiet 获取一个仅打印关键消息的安静记录器,normal 获取一个普通记录器,而verbose 获取一个打印所有内容的健谈记录器。
我想做的是模块中的一些事情,例如:
Bind<ILogger>().To<QuietLogger>().When(VerbosityParameter=="quiet");
Bind<ILogger>().To<VerboseLogger>().When(VerbosityParameter=="verbose");
Run Code Online (Sandbox Code Playgroud)
...等等。
我不知道如何做这样的事情;所有的条件绑定似乎都依赖于注入目标的状态。这样做有什么意义?当消费类必须准确详细地指定确定给定的具体类型所需的所有条件时,它难道不会打败依赖注入的全部要点吗?为什么我不能告诉 Ninject 我想要什么,然后得到它?
ninject ×2
.net ×1
biztalk ×1
constructor ×1
data-binding ×1
dynamics-crm ×1
f# ×1
linked-list ×1
linq ×1
mocking ×1
nunit ×1
obfuscation ×1
reflection ×1
security ×1
specflow ×1
tdd ×1
wcf ×1
winforms ×1
wpf ×1