当前位置: 首页 > news >正文

建筑公司网站作用ASP.NET实用网站开发答案

建筑公司网站作用,ASP.NET实用网站开发答案,我的家乡网页制作代码,软件综合课设做网站这篇文章也可以在我的博客中查看 “册”那#xff01;#xff01; 相信大家从小就被千叮万嘱要做单元测试。然后秉承这一信念#xff0c;成为了一个测试狂魔。凡有代码#xff0c;测#xff01;覆盖#xff01;最终#xff0c;一波操作猛如虎#xff1a;467测试…这篇文章也可以在我的博客中查看 “册”那 相信大家从小就被千叮万嘱要做单元测试。然后秉承这一信念成为了一个测试狂魔。凡有代码测覆盖最终一波操作猛如虎467测试0错误0自信。 第二天。 你为了优化颤抖着手更改了一行代码。果不其然发现牵连了1e9个测试用例测试结果瞬间变成满江红。 你开始怀疑自己单元测试到底为了什么除了增加大量工作量以外好像没什么好处 从此你与单元测试势不两立…………先等等 如果你有这样的疑问说明两个问题 你的单元测试做错了这篇文章会是帮助你解决问题的第一步 怎么测 在说“测什么”的时候先解决比较简单的“怎么测”问题。 没错反直觉的是“怎么测”比“测什么”更加简单…… 选择方法 单元测试野路子不多老师教的理论也无非只有两种白盒测试、黑盒测试。 那么我们应该选择哪种 太长不看黑盒测试 从现在开始可以忘掉白盒测试这个名词了……这个东西在工程上根本不实际。 你给我等等你一句话就把代码覆盖率说的一文不值 其实我也没说代码覆盖率没用我只是纯diss白盒测试。 “高代码测试覆盖率”是“代码质量高”的必要不充分条件。 白盒测试为了跑高代码覆盖率追求走遍代码的每一个角落。 嗯。是。代码覆盖率是很高了。然后呢这些用例意义的目的是什么 目的仅仅是为了得到一个高覆盖率吗 目标仅仅是刷kpi没事找事吗 它到底验证了什么问题 好好好让我们祈祷这位程序员可以保持这种劲头 因为当代码重构后可难免重新再做一轮白盒测试咯~ 说到底测试测的是软件行为而不是代码结构。 好的测试应该在代码内部重构行为不变时保持不变。利益相关者、终端用户在乎的也只有软件的行为软件内部的实现真的没人会管而如果测试依赖于代码结构那重构时改变了代码结构测试也需要连带改动。 所以这不就说明应该要用黑盒测试取代白盒测试吗 流程 那么又该使用什么流程进行单元测试 黑盒测试本身是很简单给定输入验证输出即可。 但测试目标不仅是测试通过还应是能让大伙一目了然的知道测试干的是什么被测试的函数又干的是什么。 为此我建议 一个函数一个测试情景函数名说明该测试是什么测试体中使用“准备”、“操作”、“断言”三部曲 例子 测试一个函数其作用是执行一个加法。 public int Addition(int a, int b) a b;现在测试该函数是否正常运作。 using Xunit;[Theory] [InlineData(1, 1, 2)] [InlineData(-1, 1, 0)] public void GivenTwoAddends_WhenAddition_ShouldReturnAddedValue(int addend1, int addend2, int answer) {// Given// Two addends (in parameters this case)// Whenvar result Addition(addend1, addend2);// ThenAssert.Equal(answer, result); }虽然代码是C#的但道理是相通的。 一个函数代表一个测试情景但不代表只能有一个用例。如果你想对同一操作执行多组边缘值的测试你可以考虑复用这个函数。函数名用于描述这个用例干什么是一个适合使用自然语言描述“你在干什么”的好地方。命名规范随意说明问题/其他人能接受即可。函数体清楚分为三个部分。通常使用 Given, When, Then 或者 Arrange, Act, Assert进行示意。 依赖项 如果测试中涉及到其它依赖项怎么办 由于单元测试只关注目前单元的表现单元外的逻辑即依赖项一律视为无关项。 对于无关项我们不关注它是否正确执行而是假定它正确执行 因此我们可以通过Mock等手段模拟外部依赖项让其直接返回一个预定的结果。 当然为了更好地使用Mock我们需要将外部依赖项注入到待测试的模块中。 在 ASP.NET Core 中一般实现为构造函数注入。 也就是我们需要将模块修改成依赖注入的形式。它使用到了Magic在构造函数中注入 public class MysteryAddition {private readonly Magic magic;public MysteryAddition(Magic magic) this.magic magic;/// summary/// Return a b if not magic. Return random non-negative otherwise./// /summarypublic int Addition(int a, int b){if (magic.DoMagic()){return new Random().Next();}return a b;} }该函数的定义是当Addition函数被施加了某种魔法时返回一个随机非负整数否则返回ab的结果。 这个模块使用的外部依赖Magic形式如下 public class Magic {public bool DoMagic(){// This is a very complicated magic function// Omit 100000 lines// And pretend that it returns something.return true;} }我们是需要对MysteryAddition.Addition函数进行单元测试。根据其定义会有两个分支情况而且返回的逻辑不同。 因此我们会写出两个用例。每个用例都会使用假的Magic并且假定它的不同情况 using Moq; using Xunit;[Theory] [InlineData(1, 1, 2)] [InlineData(-1, 1, 0)] public void GivenTwoAddends_WhenAdditionWithoutMagic_ShouldReturnAddedValue(int addend1, int addend2, int answer) {// Given// Two addends (in parameters this case) and ...// Setup mocked magic.var magic new MockMagic();magic.Setup(x x.DoMagic()).Returns(false); // No magic :(var service new MysteryAddition(magic.Object);// Whenvar result service.Addition(addend1, addend2);// ThenAssert.Equal(answer, result); }[Theory] [InlineData(1, 1)] [InlineData(-1, 1)] public void GivenTwoAddends_WhenAdditionWithMagic_ShouldReturnNotNegativeValue(int addend1, int addend2) {// Givenvar magic new MockMagic();magic.Setup(x x.DoMagic()).Returns(true); // Lets be magical!!!var service new MysteryAddition(magic.Object);// Whenvar result service.Addition(addend1, addend2);// ThenAssert.True(result 0); }不难看出我们所断言的只有函数的行为用例完全由函数的定义进行编写。 该过程既不考虑其它模块的正确性/干扰也不涉及函数内部的实现。 就算我不给你Addition的代码你也可以通过定义写出测试用例。 Mock很好用吧它可以模拟依赖化繁为简 但是小心成也Mock败也Mock…… 你有没有发现如果引入了Mock你还需要知道这个被模拟的依赖项在函数中起到了什么作用。 黑盒似乎变得的没那么黑了 而且更恐怖的是…… 测什么 测什么单元 好当我使用黑盒测试的原则编写了结构无关的用例后感觉上好多了…… 但感觉还是很痛苦每次测试我都要Mock一大堆依赖项 这是因为你测试了一切这是单元测试最大的痛苦来源。 有些东西它本身就不适合被单元测试…… 说到底只应编写高性价比的单元测试。 进行单元测试之前我们应该进行权衡 对这个东西写测试难不难这个单元测试给我带来的效益有多大这个单元它是否扮演了重要角色 单元测试难不难写 烂代码导致的烂测试 如果你要测的模块跟上节提及的Addition函数一样简单那没什么好说的30秒写完性价比爆高 但如果你面对一个意大利面一样的厚礼蟹代码模块 首先你扪心自问测吗 那还用问肯定不测。 然后你再扪心自问你写出这样的代码真的好吗 …… …… …… 你犹豫了因为你发现有时候单元测试难写的原因不在于单元测试本身而是因为被测试的代码太烂了 但庆幸的是这也是单元测试给你带来的“正面副作用”之一。 有没有发现当你考虑是否进行单元测试的同时你也在审视自己的代码。当你发现代码非常难测试的时候可能就是一个代码质量低的警告。你可能没有遵循单一职责原则。你的万能函数做了太多事情。 所以怎么办 重构你的代码。 将你的万能函数万能类一步步分割为更小的模块。 最终你将一个万能类A分成了4个类 A -- B-- C-- D没错此时A成为了B、C、D三个功能模块的协调者。由于B、C、D现在都仅有一个单一职责。你现在可以很轻松地对他们分别进行单元测试。性价比爆高测爆 好好好B、C、D是解决了…… 那协调者A本身呢我还要对它进行单元测试吗 单元测试的效益 是否对协调者A进行单元测试还是取决于性价比。但我劝你谨慎因为 对A进行单元测试需要解决B、C、D三个依赖项负担。如果你重构代码时对B、C、D动刀了那也意味着你可能需要修改测试用例的Mock B、C、D行为。 如果你的A类完全只是胶水代码即缝合B、C、D三个模块的。其本身逻辑基本为0那没有必要测试。如果你的A类除了使用到B、C、D三个模块以外其本身有非常复杂而必要的逻辑。A本身的独立逻辑占到了95%以上。没什么好说的进行单元测试可以确保模块没有出错。 单元测试能避免日后被这坨屎山莫名背刺四舍五入直接延年益寿。虽然你需要模拟B、C、D三个依赖项但仍然是值得的。但是也存在不少情况处于两者之间的灰色地带那么测还是不测还是选部分测见仁见智吧。 不测反正也能够在集成测试中保证模块运作。而且Mock这些依赖项太麻烦了。测别跟我说集成测试。我单元测试强迫症测完我舒服了也有双重保险了。部分测我是和事佬。你们别吵了。挑简单的测难的不测不就好了 被测单元的重要性 哥们衡量单元测试的效益不仅仅是工作量、维护性的问题还得关注这个模块本身到底重不重要。 比如这是一个支付模块要是出错可能要赔几十个甚至牢底坐穿。 那你说测不测嘛肯定得测咯 小结 当遇到难以测试的问题时第一步先别责怪单元测试本身。而是问问自己这个代码单元能不能再细分、结构优化。 当你确定已经没有优化的余地了但感觉还是难以测试考虑性价比 这个东西用到了多少依赖项本身又有多少自己的逻辑我重构这个代码包括依赖项的调用变更是否频繁我不测试会不会有严重的后果会不会有人身安全隐患 思考这三个问题自然有答案。 不要忘了即使不单元测试你还是会至少应该编写包含该模块的集成测试来确保它正常运行。 但如果你问我的想法经历了这段时间的捣鼓我会回答 不不不我大概率不会对这种东西进行单元测试。 测单元的什么 从另一个角度看待问题。 当我确定要对这个模块进行单元测试了我应该测它的啥 第一节中说要进行黑盒测试。那我们就将系统看作一个黑盒即一个一般化的物体。 我们说要测试行为其实就是测试黑盒物体与外界的交互行为。 而行为的媒介即消息。 物体与外部的交互可以视为消息的传达与回复。 所以整个问题变成了我们需要针对什么消息进行单元测试 在此之前先看看消息本身到底是什么 消息的流向 这个物体跟外界的沟通只有两个方向入向消息出向消息。 此外物体还会有内部消息流向。 如果你要我当一次灵魂画师我会画出下面这样的图 ┏━━━━━━━━┓ --[in]-- ┃ object ┃ --[out]--┗━━━━━━━━┛↓-[self]-↑从函数的角度来讲 入向消息就是单元被调用出向消息就是单元调用其它模块内部消息就是单元内部的函数调用 消息的分类 消息本身分为两类查询Query和命令Command 查询是有回复返回值但不对系统产生影响的操作 比如上面的Addition加法函数 命令是无回复但对系统产生影响的操作 比如数据库更新操作 当然也存在同时为查询和命令的操作比如Stack.Pop() 虽然如此我们还是可以按消息的类别考察某种消息是否需要被测试。 需要测试的消息 已知 消息的流向In, Out, Self消息的种类Query, Command 好我们直接做一个笛卡尔积得到6种组合。 这些组合有些是需要测试的有些是无需测试的。 魔法师Sandi Metz曾发表过一次演讲The Magic Tricks of Testing讲述了如何理解这6种组合在测试中的含义。 有兴趣的可以观看上面的演讲实在受益匪浅。 我这里就不卖关子直接剧透6种消息组合的测试操作 MessageQueryCommandIn1.a 检测结果1.b 检测直接公共副作用Self2.a 不要测试2.b 不要测试Out3.a 不要测试3.b 确保消息送出 1. 模块被调用 a: 函数有返回值 直接检测调用结果。 这就是我们第一节中测试Addition的情景 b: 如果函数无返回值 检测它的直接影响副作用。 最简单地比如一个属性有getter和setter public class Number {private int num;public int Get() num;public void Set(int num) this.num num; }只是显式举个例子C#千万别这么写。写Property拉 我们需要单元测试setter那我们可以调用setter然后使用getter检测它是否正常运作。 2. 内部消息 你为什么需要测试它 到底有谁在关注它 如果外部消息行为正确其实已经保证内部调用也正确了所以有了上一步这一步是冗余的。 3. 调用其它模块 a: 调用一个外部查询 这不就是我们第一节的第二个例子吗 外部依赖项Magic被MysteryAddition调用了。 我们站在MysteryAddition模块的角度这就是一个出向消息。我们需要对这个消息即Magic.DoMagic()的行为进行验证吗 没有吧。我们要单元测试的是MysteryAdditionMagic正不正确关我什么事喔你去找他咯。 但还没完回顾那个例子 我们要让代码执行下去以测试入向信息啊 所以遇到这种情况我们虽然不测试出向消息但如果我们需要单元测试继续执行下去需要模拟这个消息的返回。比如我们在上面使用Mock返回了假的结果。 值得一提的是生成测试替身Test Double的方式不只有Mock一种。 但话说到底这种Mock仍然是十分不自然的。如果你发现设置Mock的难度非常大建议还是遵循之前说的性价比原则 模块细分到极致 放弃单元保明智 b: 调用一个外部命令 这种情况我们不能摆烂我们需要确保命令信息成功送出了。 有人会有疑问 啊为什么为什么要管外部依赖的状态 但仔细想想这其实并不是在检测外部依赖的状态而是检测当前单元与外部依赖的衔接性。 我们单元的行为就是当执行成功时需要向外部依赖传出一个消息。 所以我们并没有脱离这个单元的范畴。 比如你要测试一个发送注册邮件的函数SendVerificationEmail它经过处理之后最终会调用邮件服务一个外部依赖发送邮件。 那么问题来了 单元测试中并没有真的邮件服务SendVerificationEmail函数并没有返回结果它也不存在任何直接副作用 那怎么知道SendVerificationEmail真的正常工作 你说得对在单元测试的范畴我们没办法100%确保它正常工作。 但我们至少可以确定一个预估行为代码应调用了邮件服务。 假设我们的外部邮件服务的接口是 public interface IEmail {public void Send(string address, string content); }我们需要单元测试的是 public class EmailMessenger {private readonly IEmail email;public EmailMessenger(IEmail email) this.email email;public void SendVerificationEmail(int userId){var address ${userId}yourdomain.com;var content $Hello, {userId} ...;// ... more processes.email.Send(address, content);} }我们就需要验证IEmail.Send仅被调用一次 [Fact] public void GivenUserId_WhenSendVerificationEmail_ShouldReallySendIt() {// Givenvar userId 1;var email new MockIEmail();email.Setup(x x.Send(It.IsAnystring(), It.IsAnystring()));var service new EmailMessenger(email.Object);// Whenservice.SendVerificationEmail(userId);// Thenemail.Verify(mock mock.Send(It.IsAnystring(), It.IsAnystring()), Times.Once()); }小结 从单元的角度消息的流向有3个方向。 其中我们只需要单元测试入向与出向消息。 入向消息 是最常规的“调用”、“预测”三部曲。 出向消息 只关注出向命令是否正常送出。而出向查询我们不测试。但有时我们需要结果让代码跑下去给它一个既定的返回值。 总结 说实话单元测试绝对是一个被低估的大魔王 它给人的感觉非常和善人畜无害 但实际上笑里藏刀 打败这个大魔王的奖励非常丰厚它可以带给我们时间、效率、收益 但是他没那么容易被打败 希望这篇文章成为你打败它的究极魔咒 师傅别念了 参考资料 不仅仅是参考资料。如果你有时间我建议你也阅读这些资料。 Test DesiderataRails Conf 2013 The Magic Tricks of Testing by Sandi MetzKatrina Owen - 467 tests, 0 failures, 0 confidence - Railsberry 2013Justin Searls – Please don’t mock meShould I write unit test for controller or service layer or both of them?Testing a service method by Unit Test?Should I bother unit testing my repository layer Bonus 如果你在想下面这些MVC中的层次是否需要单元测试可以从上面的资料获得答案。 长话短说 Repository直接集成测试不要单元测试Controller直接集成测试不要单元测试Service是否单元测试取决于该服务是否独立依赖项是否少性价比是否高
http://www.pierceye.com/news/834018/

相关文章:

  • 网站建设如何获取客户东莞网络营销销售
  • 郑州平台类网站自建房平面图设计软件
  • 昆明网站运营公司有哪些网页版微信登录二维码
  • 中国最权威的网站排名网上商店系统设计与开发
  • 自己做装修网站需要多少钱太仓建设网站
  • 湘潭做网站电话磐石网络龙岩kk社区
  • 重庆孝爱之家网站建设哪里可以做期货网站平台
  • 建设网站价位视频网站开发防止盗链
  • 制作网站的难度如何提网站建设需求
  • 做网上竞彩网站合法吗找工作用什么平台最好
  • 石家庄模板网站建网站要钱吗 优帮云
  • wap 网站 源码制作手游需要学什么软件
  • 自己做网站怎样挣钱个人网站模板 php
  • 新加坡建设局网站网站建设资料清单
  • 做网站用什么语言制作最安全?网站设计酷站
  • 河南省做网站的公司个人网站可以做电商吗
  • 专门做家教的网站网站开发大学
  • 资源专业网站优化排名wordpress 调用 置顶
  • 网站的建设维护网站换空间有影响吗
  • 兰州网站建设公南昌做网站的
  • 网站菜单样式襄樊公司网站建设
  • 学校网站建设平台wordpress 4.9.2
  • 开o2o网站需要什么手续企业微信开放平台
  • 网站开发 外文文献移动网站制作价格
  • 如何做网站的版块规划舆情监测
  • 怎么给公司注册网站二级域名的网站备案
  • 网站制作费用多少网页制作公司接单
  • ps做网站效果图房产网站cms
  • 在线教育网站建设公司互联网公司网站建设ppt模板下载
  • 泰国一家做男模的网站深圳福田有什么好玩的地方