所以 - 管理层正在努力推动在所有应用程序中进行单元测试 - 并最终进入完整的TDD /持续集成/自动构建模式(我希望).在这一点上,我们只关心让每个人使用单元测试开发应用程序.我想从基础开始.
我不会说谎 - 我在任何单位测试方面都不是专家,但我确实有足够的理解来开始基础知识的倡议,并允许我们成长为一个团队.我真的很想从你所有的专家那里得到一些评论和批评我的攻击计划.它是一个由小型商店中约10名开发人员组成的团队,这为利用敏捷开发方法和最佳实践提供了一个很好的机会.
首先 - 该团队主要由中级开发人员组成,他们有几个初级开发人员和一个高级开发人员,所有人都没有接触过单元测试.培训将是一个半月会议,每次大约30-60分钟(可能最终运行一小时,我猜,也许更频繁地使用它们).我们将继续这些会议,直到有理由阻止他们让别人赶上他们自己的"家庭作业"和经验 - 但推动将始终如一.
无论如何 - 这是我提出的课程计划.好吧,前两个至少.您的专家就课程的实际内容或结构等提出的任何建议都会很棒.评论和批评非常感谢.非常感谢.
如果这篇文章"太多"无法在此处发布或通读,我深表歉意.我认为对于希望首先进入单元测试的SO用户来说,这将是一个很好的主题.也许你可以跳到"课程计划"部分 - 再次感谢所有人.
CLIFF注意事项 - 我发现这篇帖子非常冗长和丑陋,所以这里有悬崖笔记 - 第1课将是'你好世界单元测试' - 第2课将打开我最近的应用程序的解决方案,并展示如何应用每个"世界你好"在现实生活中的例子......非常感谢大家对您给了我迄今..反馈只是wantd强调的是第2课其实是要具有现实生活的生产单元测试它,因为许多建议我这样做,当它是我的计划从开始=)
单元测试课程计划
概观
为什么单元测试?看起来像是一堆额外的工作 - 为什么呢?
•成为自己命运的主人.我们的大多数用户都没有真正的UAT,不幸的是,他们倾向于在生产中进行一次测试.通过单元测试,我们可以大大降低与此相关的风险,特别是在我们创建足够的测试数据并考虑尽可能多的顶级输入时.虽然不是防止所有错误的"银弹" - 这是你的第一道防线 - 一条巨大的前线,可与SB冠军巨人队相媲美.
•单元测试实施良好的设计和架构实践.这是"暴力的精神病患者维护你的代码并知道你住在哪里".你根本无法编写经过单元测试的低质量代码
•你有多少次没有重构臭代码,因为你太害怕破坏某些东西?自动化测试消除了这种恐惧,使重构变得更加容易,从而使代码更易读,更易于维护.
•底线 - 维护变得更容易和更便宜.编写单元测试所花费的时间现在可能成本很高 - 但是它节省你的时间已经被证明是一次又一次更有价值.这是自动测试代码的首要原因.它给了我们信心,使我们能够对系统进行更加雄心勃勃的改变,否则我们可能不得不降低需求,甚至根本不采取任何措施.
术语审查
•单元测试 - 测试最低级别的单个工作单元.EG - 测试单个函数可以流经的所有可能的代码路径.
•集成测试 - 测试您的单元如何协同工作.例如 - 运行一个"作业"(或一系列函数调用),使用已知输入执行大量工作 - 然后在最后查询数据库并断言值是您对这些已知输入的期望(而不是必须眼球在某个网页上的网格,例如进行功能测试).
•伪造 - 假冒是一种对象,其目的是用于您的测试.它允许您轻松地不测试您不想测试的代码.您不必调用您不想要的代码(如数据库调用),而是使用假对象来"伪造"该DB调用,并且可能从XML/Excel文件或模拟框架中读取数据.o模拟 - 一种你对其发表断言声明的假货.o Stub - 一种用作占位符代码的伪造,因此您可以跳过数据库调用,但不要对其进行断言
教训
第一课 - Hello Worlds
•Hello World单元测试 - 我将创建一个经过单元测试的"hello world"控制台应用程序.将在会议期间动态创建此应用程序,在Visual Studio …
我希望这个问题不是"有争议的" - 我只是基本上问 - 有没有人在这里购买过TypeMock并对结果感到高兴(或不满意)?
我们是一个只有12名开发人员的小型开发商店,其中包括2名开发经理.到目前为止我们一直在使用NMock,但是有局限性.我做过研究并开始玩TypeMock,我很喜欢它.它是超级干净的语法,让你基本上模拟一切,这对遗留代码很有用.
问题是 - 我如何证明我的老板每个许可证花费800-1200美元用于拥有4-5个完全免费竞争对手的API?800-1200 $是每个许可证的Infragistrics或Telerik成本 - 并且肯定不是4-5开源可比的UI框架...这就是为什么我发现它有点高估,虽然是一个很棒的库......
任何意见/经验都非常感谢.
编辑:找到MOQ之后我以为我爱上了 - 直到我发现VB.NET中没有完全支持它,因为VB缺少lambda子例程=(.是否有人使用MOQ进行VB.NET?问题是我们是混合的商店 - 我们使用C#进行CRM开发,使用VB进行其他任何操作.我们再次非常感谢任何指导
编辑:嗯..我在Moq找不到Isolate.WhenCalled()equivalen ...这里有什么帮助吗?我想存根/模拟一个CONCRETE对象的ReadOnly属性(不是模拟对象)...我可以用Isolate.WhenCalled与TM轻松地做到这一点.怎么用Moq ???
我有一个这样的课:
public class FooController : ApiController
{
[System.Web.Http.Route("live/topperformers")]
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpGet]
public List<string> GetTopPerformers()
{
return new List<string>();
}
}
Run Code Online (Sandbox Code Playgroud)
当我通过访问" http://foo.com/live/topperformers " 访问它时,效果很好.所以现在我想为这个方法添加一个可选的DateTime参数,所以我修改了方法以获取DAteTime参数,并使其可以为空.
public class FooController : ApiController
{
[System.Web.Http.Route("live/topperformers/{dateTime:DateTime}")]
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpGet]
public List<string> GetTopPerformers(DateTime? dateTime)
{
return new List<string>();
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试访问没有参数的URL时,就像我之前访问的那样 - 它给出了404.在日期值中像"喜欢"一样http://foo.com/live/topperformers/2010-01-01 "工作正常.但没有约会,它给出了404.
我认为Web API以这种方式支持可选参数?我可以简单地重载并拥有两个版本,但这只能通过一种方法实现吗?
我对单元测试和TDD"相对较新".最近才完成我的第一个生产应用程序(至少在理论上)100%的代码覆盖率.我已经在以前的项目中进行了单元测试一段时间,但是没有真正的TDD方式和良好的代码覆盖率.它一直是一种思想.我觉得我现在对它有很好的把握.
我也正在努力培训团队的其他成员进行TDD和单元测试,以便我们能够在所有应用程序中进行单元测试,并开始向前发展,最终进展到完全TDD w /自动构建和连续积分.我在这里发布了一个关于我的攻击计划/培训议程的评论和批评.
其中一个回复(事实上是最高投票)建议我在进行培训之前首先设置基础设施.不幸的是,我没有接触到这一点,谷歌搜索主题是困难的,因为CruiseControl.NET/nAnt/etc的页面并没有真正解释为什么我们应该设置它以及'如何'一切连接到geather.
我们是一个小商店(大约10个开发人员),几乎只使用微软技术,并在VB.NET中进行开发.我们期待最终开始使用C#,但那是另一次.我一直在使用VS2008附带的MSTest项目进行单元测试,我一直在使用Visual Studio构建我的应用程序,并使用MSI安装项目进行部署......我们(不幸的是)也使用VSS进行我们的控制 - 但这也是在砧板上,我真的想摆脱它并使用颠覆.
我知道我需要使用CruiseControl.NET for CI,以及nAnt或MSBuild来构建应用程序.我可能需要一个构建服务器来运行所有这些构建.但我找不到任何"连接"点并解释它们如何与彼此交互,构建服务器上应该是什么,何时应该使用构建服务器构建(仅用于部署构建,或者甚至是只是想在您的本地环境中进行一些小改动之后编译您正在开发的应用程序?).我也计划削减MSTest,因为我发现它是有缺陷的并且将使用nUnit.
任何人都可以说明我从"知道如何做TDD"到"建立适当的基础设施以便整个团队能够做到并努力工作"这个差距吗?我确实理解了持续集成是什么,但同样,我不确定应该如何设置构建服务器以及它如何与所有内容连接,以及为什么我们需要一个(例如管理层).
非常感谢你花时间陪伴.
我需要什么部分的终结者?似乎与最终的建造者和团队城市有一些重叠.Finalbuilder服务器似乎是一个CI服务器,所以我猜我不需要它.FinalBuilder似乎是一个构建服务器 - 但我认为TeamCity也是一个构建服务器......而Automise似乎是一个可视化的Windows自动化工具,就像winforms应用程序的某种开发平台一样......
_I在Team City支持的应用程序图中也没有看到对最终构建器的支持:_
我有一个带有Web前端,WCF Windows服务后端的.NET应用程序.应用程序非常简单 - 需要一些用户输入,将其发送到服务.该服务执行此操作 - 获取输入(Excel电子表格),提取数据项,检查SQL DB以确保项目尚不存在 - 如果它们不存在,我们向第三方数据供应商发出实时请求并检索结果,将它们插入数据库.它沿途做了一些记录.
我有一个Job类,有一个公共ctor和公共Run()方法.ctor接受所有参数,Run()方法执行上述所有逻辑.每个逻辑功能部分被拆分为一个单独的类 - IParser执行文件解析,IConnection执行与数据供应商的交互,IDataAccess执行数据访问等.Job类具有这些接口的私有实例,并使用DI构建默认情况下实际实现,但允许类用户注入任何接口.
在实际代码中,我使用默认的ctor.在我对Run()方法的单元测试中,我使用通过NMock2.0创建的所有模拟对象.此Run()方法本质上是此应用程序的"顶级"功能.
现在这是我的问题/问题:这个Run()方法的单元测试很疯狂.我有三个模拟对象,我发送到ctor,每个模拟对象设置自己的期望.最后,我验证.我有一些Run方法可以采用的不同流程,每个流程都有自己的测试 - 它可以找到数据库中的所有内容,而不是向供应商发出请求......或者可以抛出异常并且作业状态可以被设置为'失败'...或者我们可以得到我们没有数据并且需要发出供应商请求的情况(因此需要进行所有这些函数调用).
现在 - 在你对我大喊并说'你的Run()方法过于复杂之前!' - 这个Run方法只有50行代码!(它确实调用了一些私有函数;但整个类只有160行).由于所有"真实"逻辑都是在此类声明的接口中完成的.但是,这个函数最大的单元测试是80行代码,有13个调用Expect.BLAH().. _
这使得重新考虑了巨大的痛苦.如果我想改变这个Run()方法,我必须编辑我的三个单元测试并添加/删除/更新Expect()调用.当我需要重构时,我最终花费更多时间创建模拟调用,而不是实际编写新代码.在这个功能上做真正的TDD使得它变得更加困难,如果不是不可能的话.它让我觉得它根本不值得对这个顶级函数进行单元测试,因为实际上这个类没有做太多逻辑,它只是将数据传递给它的复合对象(它们都是完全单元测试的,不需要嘲讽).
那么 - 我是否应该费心去测试这个高级功能呢?这样做我获得了什么?或者我在这里完全滥用mock/stub对象?也许我应该废弃这个类的单元测试,而只是进行自动化集成测试,它使用对象的实际实现和Asserts()对SQL查询来确保存在正确的最终状态数据?我在这里错过了什么?
编辑:这是代码 - 第一个函数是实际的Run()方法 - 然后我的五个测试测试所有五个可能的代码路径.我因为NDA原因改变了一些,但一般的概念仍然存在.你对我如何测试这个功能有什么看错了,有什么改变的建议让它变得更好?谢谢.
我确实在这个网站上做了一些谷歌搜索和搜索,但没有找到我正在寻找的确切内容.
我希望有人可以在这里指出我正确的方向.我是一名ASP.NET/SQL Server开发人员,希望开发一个(基本的)基本社交网站(喘气).在我从头开始使用ASP.NET中的空白解决方案之前,我想知道是否有任何特定于ASP.NET的框架可以作为一个很好的起点.我已经考虑将Google Maps jquery控件用于我的Google Maps集成,以及对我的社交网站共享集成的"sharethis"控件.用于人工认证的Captcha ......但除此之外,我不确定我可以利用什么......谷歌上的任何内容都没有按照我的搜索条件跳出来.
我也想知道是否有其他人做过类似的事情并且可以和我分享他们的死后故事.
我也愿意学习一种新的平台/语言,如果这意味着节省时间 - 我的经验主要是在ASP.NET中,所以如果它最有意义的话,那就是我计划使用的.我最初的要求是基本和现实的 - 配置文件设置(图像,信息等),'组'创建,谷歌地图集成,群组共享的日历控件,短信支持,群组间的讨论论坛,搜索群组,最有可能的OpenID集成等等.我不会尝试构建整个站点然后将其发布,但是要采取一些步骤并一次发布一些功能.
对于像这样的广泛问题,我们非常感谢任何建议.再次感谢.
我发现DotNetOpenAuth 似乎是一个很好的API,用于处理ASP.NET Web表单的OpenID.他们还有一个ASP.NET MVC版本
我还找到了MS Web Platform.这看起来像一些好东西.有人曾经使用它并认为它适用于这种类型的应用程序吗?
我找到了一个名为ActiveSocial的 DotNetNuke库.它的价格合适(500美元)并且不仅仅是我需要的功能,但缺少一些功能.我想知道这里有没有人曾经使用过AS.DNN是否易于扩展,因此我可以添加Google地图功能等?如果AS附带源代码,它不会说雪覆盖的任何地方(销售AS的供应商).如果没有,那么我可能会被搞砸,因为我无法集成我想要的功能.
sql-server asp.net frameworks web-frameworks social-networking
我已经尝试使用system()和fork(),尝试过exec(),但仍然没有得到我需要的东西.
我想写一个Perl脚本,它连续5次执行不同的Perl脚本(发送不同的参数值),但让它同时运行.我意识到我可以将我的脚本变成.pm文件并引用它但我宁愿保持子脚本独立于父...
Perl(我使用WindowsXP)执行进程是不是一种简单的方法,而不关心返回值或antyhing,只是继续进入父脚本的下一行?
我有一个类API,它具有完整的代码覆盖率,并使用DI来模拟主类函数(Job.Run)中的所有逻辑,它完成所有工作.
我在生产中发现了一个错误,我们没有对其中一个数据输入字段进行验证.
所以,我添加了一个名为ValidateFoo()的存根函数...对这个函数写了一个单元测试来预测一个JobFailedException,运行测试 - 它明显失败,因为该函数是空的.我添加了验证逻辑,现在测试通过了.
太好了,现在我们知道验证工作了.问题是 - 如何编写测试以确保在Job.Run()中实际调用ValidateFoo()?ValidateFoo()是Job类的私有方法 - 因此它不是接口...
无论如何用NMock2.0做到这一点?我知道TypeMock支持非接口类型的假货.但是现在改变模拟库不是一种选择.此时如果NMock不支持它,我只需将ValidateFoo()调用添加到Run()方法并手动测试 - 显然我不想考虑我的Job.Run()方法现在100%覆盖.任何建议?非常感谢,非常感谢.
编辑:我想到的另一个选择是为我的Job.Run功能创建一个集成测试(向它注入复合对象的真实实现而不是模拟).我将为该字段给它一个错误的输入值,然后验证作业失败.这工作并涵盖了我的测试 - 但它不是真正的单元测试,而是测试一个功能单元的集成测试....嗯..
EDIT2:有没有办法做什么?有人有想法吗?也许TypeMock - 或更好的设计?
我有一个简单的字符串类扩展方法,它将从字符串中删除所有非数字字符.因此,如果我有一个字符串,例如电话号码,如"(555)215-4444",它会将其转换为"5552154444".它看起来像这样:
public static string ToDigitsOnly(this string input)
{
Regex digitsOnly = new Regex(@"[^\d]");
return digitsOnly.Replace(input, String.Empty);
}
Run Code Online (Sandbox Code Playgroud)
我只是想知道在这里处理空值的最优雅方法是什么?在这些情况下是否存在典型模式,例如,如果传入null,则返回null值?看来,因为我在这里扩展字符串类,我可能想要允许空值而不抛出争论异常(因为我在使用它时并没有真正传递争论......)?但是有些人可能会说我应该像普通的方法那样抛出异常.你在这里使用的最佳做法是什么?
谢谢!
我刚刚在同事代码中遇到过这个问题.他有一个可以考虑的bool类型,他比较如下:
//foo has no value here and evaluated to false
if(foo==true)
{
doSomething();
}
Run Code Online (Sandbox Code Playgroud)
通常,我检查可以为空的布尔值的方式是这样的:
bool IsTrue(bool? value)
{
return value.HasValue && value.Value;
}
if(IsTrue(foo)){
doSomething()
}
Run Code Online (Sandbox Code Playgroud)
编辑:我运行了两种方法,它们看起来都是一样的.我问的是哪一个是正确的方法,如果需要额外的检查?
现在我正在质疑我自己和我的同事代码.我在这里做这个额外的检查有什么意义吗?或者我可以安全地做第一种方式吗?
谢谢(是的,我确实搜索了这个!:))
tdd ×4
c# ×3
mocking ×3
unit-testing ×3
asp.net ×2
typemock ×2
frameworks ×1
moq ×1
nmock ×1
nullable ×1
perl ×1
sql-server ×1
windows ×1