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

网站建设书电子商务网站开发的任务书

网站建设书,电子商务网站开发的任务书,深圳深网站建设服务,南宁seo推广外包Photo #xff1a;UnitTesting文 | Edison Zhou上一篇我们学习了单元测试的核心技术#xff1a;存根、模拟对象和隔离框架#xff0c;它们是我们进行高质量单元测试的技术基础。本篇会集中在管理和组织单元测试的技术#xff0c;以及如何确保在真实项目中进行高质量的单元测… Photo UnitTesting文 | Edison Zhou上一篇我们学习了单元测试的核心技术存根、模拟对象和隔离框架它们是我们进行高质量单元测试的技术基础。本篇会集中在管理和组织单元测试的技术以及如何确保在真实项目中进行高质量的单元测试。测试的组织与层次 测试项目的两种目录结构1集成测试和单元测试在同一个项目里但放在不同的目录和命名空间里。基础类放在单独的文件夹里。2集成测试和单元测试位于不同的项目中有不同的命名空间。实践中推荐使用第二种目录结构因为如果我们不把这两种测试分开人们可能就不会经常地运行这些测试。既然测试都写好了为什么人们不愿意按照需要运行它们呢一个原因是开发人员有可能懒得运行测试或者没有时间运行测试。构建绿色安全区将集成测试和单元测试分开放置其实就给团队的开发人员构建了绿色安全区这个区只包含单元测试。因为集成测试的本质决定了它运行时间较长开发人员很有可能每天运行多次单元测试较少运行集成测试。单元测试全部通过至少可以使开发人员对代码质量比较有信心专注于提高编码效率。而且我们应该将测试自动化编写每日构建脚本并借助持续集成工具帮助我们自动执行这些脚本。将测试类映射到被测试代码1将测试映射到项目创建一个测试项目用被测试项目的名字加上后缀.UnitTests来命名。例如EDC.MyLibrary → EDC.MyLibrary.UnitTests 和 EDC.MyLibrary.IntegrationTests这种方法看起来简单直观开发人员能够从项目名称找到对应的所有测试。2将测试映射到类① 每个被测试类或者被测试工作单元对应一个测试类LogAnalyzer → LogAnalyzer.UnitTests② 每个功能对应一个测试类有一个LoginManager类测试方法为ChangePassword这个方法测试用例特别多需要单独放在一个测试类里边 → 创建两个类 LoginManagerTests 和 LoginManagerTests-ChangePassword前者只包含对ChangePassword方法的测试后者包含该类其他所有测试。3将测试映射到具体的工作单元入口测试方法的命名应该有意义这样人们可以很容易地找到所有相关的测试方法。这里回归一下第一篇中提到的测试方法名称的规范一般包含三个部分[UnitOfWorkName]_[ScenarioUnderTest]_[ExpectedBehavior]UnitOfWorkName  被测试的方法、一组方法或者一组类Scenario  测试进行的假设条件例如“登入失败”“无效用户”或“密码正确”等ExpectedBehavior  在测试场景指定的条件下你对被测试方法行为的预期 示例IsValidFileName_BadExtension_ReturnsFalseIsValidFileName_EmptyName_Throws 等注入横切关注点当需要处理类似时间管理、异常或日志的横切关注点时使用它们的地方会非常多如果把它们实现成可注入的产生的代码会很容易测试但却很难阅读和理解。这里我们来看一个例子假设应用程序使用当前时间进行写日志相关代码如下 public static class TimeLogger{public static string CreateMessage(string info){return DateTime.Now.ToShortDateString() info;}} 为了使这段代码容易测试如果使用之前的依赖注入技术那么我们需要创建一个ITimeProvider接口还必须在每个用到DateTime的地方使用到这个接口。这样做非常耗时实际上还有更直接的方法解决这个问题。Step1.创建一个名为SystemTime的定制类在所有的产品代码里边使用这个定制类而非标准的内建类DateTime。 public class SystemTime{private static DateTime _date;public static void Set(DateTime custom){_date custom;}public static void Reset(){_date DateTime.MinValue;}public static DateTime Now{get{// 如果设置了时间SystemTime就返回假时间否则返回真时间if (_date ! DateTime.MinValue){return _date;}return DateTime.Now;}}} 阅读这段代码其中有一个小技巧SystemTime类提供一个特殊方法Set它会修改系统中的当前时间也就是说每个使用这个SystemTime类的人看到的都是你指定的日期和时间。有了这样的代码每个使用这个SystemTime类的人看到的都会是你指定的日期和时间。Step2.在测试项目中使用SystemTime进行测试。 [TestFixture]public class TimeLoggerTests{[Test]public void SettingSystemTime_Always_ChangesTime(){SystemTime.Set(new DateTime(2000, 1, 1));string output TimeLogger.CreateMessage(a);StringAssert.Contains(2000/1/1, output);}/// summary/// 在每个测试结束时重置日期/// /summary[TearDown]public void AfterEachTest(){SystemTime.Reset();}} 在测试中我们首先假定设置一个日期然后进行断言。并且借助TearDown方法确保当前测试不会改变其他测试的值。Note  这样做的好处就在于不用注入一大堆接口我们所付出的代价仅仅在于在测试类中加入一个简单的[TearDown]方法确保当前测试不会改变其他测试的值。使用测试使测试代码可重用推荐大家在测试代码中使用继承机制通过实现基类可以较好地展现面向对象的魔力。在实践中一般有三种模式会被使用到1抽象测试基础结构类模式 /// summary/// 测试类集成模式/// /summary[TestFixture]public class BaseTestsClass{/// summary/// 重构为通用可读的工具方法由派生类使用/// /summary/// returnsFakeLogger/returnspublic ILogger FakeTheLogger(){LoggingFacility.Logger Substitute.ForILogger();return LoggingFacility.Logger;}[TearDown]public void ClearLogger(){// 测试之间要重置静态资源LoggingFacility.Logger null;}}[TestFixture]public class LogAnalyzerTests : BaseTestsClass{[Test]public void Analyze_EmptyFile_ThrowsException(){// 调用基类的辅助方法FakeTheLogger();LogAnalyzer analyzer new LogAnalyzer();analyzer.Analyze(myemptyfile.txt);// 测试方法的其余部分}} 使用此模式要注意继承最好不要超过一层如果继承层数过多不仅可读性急剧下降编译也很容易出错。2测试类类模板模式 /// summary/// 测试模板类模式/// /summary[TestFixture]public abstract class TemplateStringParserTests{[Test]public abstract void TestGetStringVersionFromHeader_SingleDigit_Found();[Test]public abstract void TestGetStringVersionFromHeader_WithMinorVersion_Found();[Test]public abstract void TestGetStringVersionFromHeader_WithRevision_Found();}[TestFixture]public class XMLStrignParserTests : TemplateStringParserTests{protected IStringParser GetParser(string input){return new XMLStringParser(input);}[Test]public override void TestGetStringVersionFromHeader_SingleDigit_Found(){IStringParser parser GetParser(Header1/Header);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(1, versionFromHeader);}[Test]public override void TestGetStringVersionFromHeader_WithMinorVersion_Found(){IStringParser parser GetParser(Header1.1/Header);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(1.1, versionFromHeader);}[Test]public override void TestGetStringVersionFromHeader_WithRevision_Found(){IStringParser parser GetParser(Header1.1.1/Header);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(1.1, versionFromHeader);}} 使用此模式可以确保开发者不会遗忘重要的测试基类包含了抽象的测试方法派生类必须实现这些抽象方法。3抽象测试驱动类模式/// summary /// 抽象“填空”测试驱动类模式 /// /summary public abstract class FillInTheBlankStringParserTests {// 返回接口的抽象方法protected abstract IStringParser GetParser(string input);// 抽象输入方法属性为派生类提供特定格式的数据protected abstract string HeaderVersion_SingleDigit { get; }protected abstract string HeaderVersion_WithMinorVersion { get; }protected abstract string HeaderVersion_WithRevision { get; }// 如果需要预先为派生类定义预期的输出public const string EXPECTED_SINGLE_DIGIT 1;public const string EXPECTED_WITH_MINORVERSION 1.1;public const string EXPECTED_WITH_REVISION 1.1.1;[Test]public void TestGetStringVersionFromHeader_SingleDigit_Found() {string input HeaderVersion_SingleDigit;IStringParser parser GetParser(input);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(EXPECTED_SINGLE_DIGIT, versionFromHeader);}[Test]public void TestGetStringVersionFromHeader_WithMinorVersion_Found() {string input HeaderVersion_WithMinorVersion;IStringParser parser GetParser(input);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(EXPECTED_WITH_MINORVERSION, versionFromHeader);}[Test]public void TestGetStringVersionFromHeader_WithRevision_Found() {string input HeaderVersion_WithRevision;IStringParser parser GetParser(input);string versionFromHeader parser.GetTextVersionFromHeader();Assert.AreEqual(EXPECTED_WITH_REVISION, versionFromHeader);} }public class DBLogStringParserTests : GenericParserTestsDBLogStringParser {protected override string GetInputHeaderSingleDigit() {return Header;1;}protected override string GetInputHeaderWithMinorVersion() {return Header;1.1;}protected override string GetInputHeaderWithRevision() {return Header;1.1.1;} } 此模式在基类中实现测试方法并提供派生类可以实现的抽象方法钩子。当然只是大部分的测试代码在基类中派生类也可以加入自己的特殊测试。此模式的要点在于你不是具体地测试一个类而是测试产品代码中的一个接口或者基类。当然在.NET中我们也可以通过泛型来实现此模式例如下面的代码 public abstract class GenericParserTestsT where T : IStringParser // 01.定义参数的泛型约束{protected abstract string GetInputHeaderSingleDigit();protected abstract string GetInputHeaderWithMinorVersion();protected abstract string GetInputHeaderWithRevision();// 02.返回泛型变量而非接口protected T GetParser(string input) {// 03.返回泛型return (T)Activator.CreateInstance(typeof(T), input);}[Test]public void TestGetStringVersionFromHeader_SingleDigit_Found() {string input GetInputHeaderSingleDigit();T parser GetParser(input);bool result parser.HasCorrectHeader();Assert.AreEqual(false, result);}[Test]public void TestGetStringVersionFromHeader_WithMinorVersion_Found() {string input GetInputHeaderWithMinorVersion();T parser GetParser(input);bool result parser.HasCorrectHeader();Assert.AreEqual(false, result);}[Test]public void TestGetStringVersionFromHeader_WithRevision_Found() {string input GetInputHeaderWithRevision();T parser GetParser(input);bool result parser.HasCorrectHeader();Assert.AreEqual(false, result);}}public class DBLogStringParserTests : GenericParserTestsDBLogStringParser{protected override string GetInputHeaderSingleDigit() {return Header;1;}protected override string GetInputHeaderWithMinorVersion() {return Header;1.1;}protected override string GetInputHeaderWithRevision() {return Header;1.1.1;}} 优秀单元测试的支柱 要编写优秀的单元测试它们应该同时具有 可靠性、可维护性 及 可读性。编写可靠的单元测试一个可靠的测试能让你觉得自己对事态了如指掌能够从容应对。以下是一些指导原则和技术1决定何时删除或修改测试一旦测试写好并通过通常我们不应该修改或删除这些测试因为它们是我们得绿色保护网。但是有时候我们还是需要修改或者删除测试所以需要理解什么情况下修改或删除测试会带来问题什么情况下又是合理的。一般来说如果有产品缺陷、测试缺陷、语义或者API更改或者是由于冲突或无效测试我们需要修改和删除测试代码。2避免测试中的逻辑随着测试中逻辑的增多出现测试缺陷的几率就会呈现指数倍的增长。如果单元测试中包含了下列语句就是包含了不应该有的逻辑switch、if或else语句foreach、for或while循环这种做法不值得推荐因为这样的测试可读性较差也比较脆弱。通常来说一个单元测试应该是一系列方法的调用和断言但是不包含控制流程语句甚至不应该将断言语句放在try-catch中。3只测试一个关注点如果我们的单元测试对多个对象进行了断言那么这个测试有可能测试了多个关注点。在一个单元测试中验证多个关注点会使得事情变得复杂却没有什么价值。你应该在分开的、独立的单元测试中验证多余的关注点这样才能发现真正失败的地方。4把单元测试和集成测试分开掐面讨论了测试的绿色安全区我们需要的就是准备一个单独的单元测试项目项目中仅包含那些在内存中运行结果稳定可重复执行的测试。5用代码审查确保代码覆盖率如果覆盖率低于20%说明我们缺少很多测试我们不会知道下一个开发人员将怎么修改我们得代码。如果没有回失败的测试可能就不会发现这些错误。编写可维护的单元测试可维护性是大多数开发者在编写单元测试时面对的核心问题之一。为此我们需要1只测试公共契约2删除重复测试去除重复代码3实施测试隔离测试隔离的基本概念是一个测试应该总是在它自己的小世界中运行与其他类似或不同的工作的测试隔离甚至不知道其他测试的存在。编写可读的单元测试不可读的测试几乎没有任何意义它是我们向项目的下一代开发者讲述的故事帮助开发者理解一个应用程序的组成及其开端。1单元测试命名这个前面我们讨论过应该包括三部分被测试方法名_测试场景_预期行为如果开发人员都是用这种规范其他的开发人员就能很容易进入项目理解测试。2变量命名通过合理命名变量你可以确保阅读测试的人可以尽快地理解你要验证什么相对于理解产品代码中你想要实现什么。请看下面的一个例子 [Test]public void BadlyNameTest() {LogAnalyzer log new LogAnalyzer();int result log.GetLineCount(abc.txt);Assert.AreEqual(-100, result);}[Test]public void GoodNameTest() {LogAnalyzer log new LogAnalyzer();int result log.GetLineCount(abc.txt);const int COULD_NOT_READ_FILE -100;Assert.AreEqual(-COULD_NOT_READ_FILE, result);} 经过改进后我们会很容易理解这个返回值的意义。3有意义的断言只有当测试确实需要并且找不到别的办法使测试更清晰时你才应该编写定制的断言信息。编写好的断言信息就像编写好的异常信息一不小心就会犯错使读者产生误解浪费他们的时间。4断言和操作分离为了可读性请不要把断言和方法调用写在同一行。// 断言和操作写在了同一行 Assert.AreEqual(-COULD_NOT_READ_FILE, log.GetLineCount(abc.txt)); 小结 这一篇我们学习了尽量将测试自动化尽可能多次地运行测试尽可能持续地进行产品交付把集成测试和单元测试分开为整个团队构建一个绿色安全区该区域中所有的测试都必须通过按照项目和类型组织测试把测试分别放在不同的目录、文件夹或者命名空间中使用测试类层次对一个层次中相关的几个类进行同一组测试或者对共享一个通用接口或者基类的类型进行同一组测试优秀单元测试具有三大支柱可读性、可维护性与可靠性它们相辅相成。如果人们能读懂你的测试就能理解和维护测试如果测试能够通过它们也会信任测试。一旦实现这个目标你就能知道系统是否正常工作具有了处理变更和在需要时修改代码的能力参考资料  1Roy Osherove 著金迎 译《单元测试的艺术第2版》2020后记虽然这是一篇发表于2015年的文章但我至今觉得仍有价值。因为我发现在.NET圈还是有很多童鞋不了解单元测试和不喜欢写单元测试不懂其价值就不会形成增强回路。所谓增强回路就是我单元测试写的越多以后修改代码增加功能就不容易出现Bug这里主要指SIT阶段、UAT阶段乃至线上越不容易出现Bug我提交的代码质量就越高就会增强我写单元测试的愿望形成一个回路。在我现在的实践中是把单元测试加入了持续集成构建任务中的每次组员提交代码都会触发构建任务去编译项目去跑单元测试只要单元测试没有跑过就会邮件或者通知发出来告诉我我会知道是谁提交的代码居然没有跑单元测试就提交了我就会找他改Bug了呵呵。The End「 码字不易也希望各位看官看完觉得还行就在本文右下方顺手点个“在看”那就是对我最大的鼓励如果觉得很好也可以转发给你的朋友让更多人看到独乐乐不如众乐乐是吧」往期精彩回顾.NET Core on K8S学习与实践系列文章索引目录.NET Core 微服务学习与实践系列文章索引目录【资料】2019 .NET China Conf 大会资料下载【视频】2019 .NET China Conf 大会视频发布2019 .NET China Conf 路一直都在社区会更好基于Jenkins的开发测试全流程持续集成实践基于Jenkins Pipeline的.NET Core持续集成实践【导读】我读经典心旷神怡 - 经典书籍读后感汇总【导读】我的诗和远方 - 也读唐诗与旅游游记汇总点个【在看】如何?
http://www.zqtcl.cn/news/321530/

相关文章:

  • 如何建设教师网上授课网站重庆建设网站哪家专业
  • 企业网站页头背景图建设三轮摩托车官网
  • 直播网站创做上海idc机房托管
  • 受欢迎自适应网站建设地址c2c二手车交易平台
  • 做个平台网站怎么做房价查询
  • 自学网站建设最快要多久asp.net 手机网站开发
  • 淮安做网站找哪家公司verycloud wordpress
  • 无法连接到wordpress站点网站建设的 几点
  • 网站免费空间购买wordpress支持页面模版
  • 腾讯建设网站视频宁波城乡住房建设厅网站
  • 乐清网站开发公司个人网站建设工作室
  • 网站空间升级通知手机端怎么看世界杯
  • 广西南宁网站推广建设网站视频教程
  • 福州专业网站建设推广费用nas可做网站服务器吗
  • 齐鲁建设网站福建省高速公路建设管理网站
  • 比格设计网站官网收录网站查询
  • 国外做直播网站淘宝电商网站怎么做的
  • 国外私人网站网站由那些组成
  • 网站备案多久通过机械设备网站
  • 企业自建站案例网站基础知识域名5个点
  • 咸宁建设网站海口市网站建设
  • 认识电子商务网站建设技术网站交换链接怎么做?
  • 定制商城网站建设全球搜索引擎排名2021
  • 徐州百度网站快速优化做网站视频图片加载不出来
  • 网站被host重定向处理浙江网新股吧
  • asp国外网站什么页游好玩
  • 高端简约30平米办公室装修广州搜索seo网站优化
  • 海口的网站建设公司wordpress二次元极简主题
  • 南京快速建站公司国家网站域名
  • 兰州装修公司哪家好网站seo推广员招聘