Questions tagged «testing»

根据软件系统的预期行为来验证该软件系统的行为。

10
单元测试应用程序逻辑和不信任的语言构造之间的界线在哪里?
考虑这样的函数: function savePeople(dataStore, people) { people.forEach(person => dataStore.savePerson(person)); } 可以这样使用: myDataStore = new Store('some connection string', 'password'); myPeople = ['Joe', 'Maggie', 'John']; savePeople(myDataStore, myPeople); 让我们假设它Store具有自己的单元测试,或由供应商提供。无论如何,我们都相信Store。让我们进一步假设错误处理(例如,数据库断开错误)不是的责任savePeople。确实,让我们假设商店本身是一个神奇的数据库,它不可能以任何方式出错。 鉴于这些假设,问题是: 应该savePeople()进行单元测试,还是将这些测试等同于测试内置forEach语言结构? 当然,我们可以传递一个模拟dataStore并断言dataStore.savePerson()每个人都会被调用一次。您当然可以说这样的测试可提供针对实现更改的安全性的论据:例如,如果我们决定forEach用传统的for循环或某种其他迭代方法代替。因此,测试并非完全无关紧要。但是它似乎非常接近... 这是另一个可能更富有成效的例子。考虑一个仅协调其他对象或功能的功能。例如: function bakeCookies(dough, pan, oven) { panWithRawCookies = pan.add(dough); oven.addPan(panWithRawCookies); oven.bakeCookies(); oven.removePan(); } 假设您认为这样的功能应该如何进行单元测试?这是我很难想象任何种类的单元测试的不只是嘲笑dough,pan和oven,然后断言方法被调用它们。但是这样的测试无非是复制了该函数的确切实现。 无法以有意义的黑盒方式测试功能是否表明功能本身存在设计缺陷?如果是这样,如何改进? 为了更清楚地说明激发bakeCookies示例的问题,我将添加一个更现实的场景,该场景是我尝试向其添加代码并重构遗留代码时遇到的一种情况。 当用户创建新帐户时,需要做很多事情:1)需要在数据库中创建新用户记录2)需要发送欢迎电子邮件3)需要记录用户的IP地址以防欺诈目的。 因此,我们想创建一个将所有“新用户”步骤联系在一起的方法: function createNewUser(validatedUserData, emailService, dataStore) …

6
强制执行单元测试的执行命令是不好的做法吗?
我正在为一个包含多个子模块的项目编写测试。我编写的每个测试用例彼此独立运行,并且清除测试之间的所有数据。 尽管测试是独立运行的,但由于某些情况需要多个子模块,因此我正在考虑执行执行顺序。例如,一个子模块正在生成数据,而另一个正在对数据运行查询。如果生成数据的子模块包含错误,则即使子模块本身工作正常,查询子模块的测试也将失败。 我无法使用虚拟数据,因为我正在测试的主要功能是与黑匣子远程服务器的连接,该服务器仅从第一个子模块获取数据。 在这种情况下,可以强制执行测试的执行顺序还是不好的做法?我感觉此设置中有异味,但找不到更好的方法。 编辑:问题来自于如何构建测试,其中一个测试是另一测试的设置?因为“先前”测试不是设置,而是测试执行设置的代码。

27
为什么要让/不让开发人员测试自己的作品
我想收集一些争论,为什么让开发人员在产品投入生产前的最后一步测试自己的工作是一个坏主意,因为不幸的是,我的工作地点有时会这样做(这是最后一次出现,这种说法归结为大多数人太忙于其他事情,而又没有时间让另一个人熟悉程序的那部分-这是非常专业的软件)。 在这种情况下有测试计划(尽管并非总是如此),但我非常赞成让一个没有进行测试变更的人实际进行最终测试。因此,我想问您能否为我提供一个良好而可靠的论点清单,以便下次讨论时可以提出。或者提供反驳,以防万一您认为这很好,尤其是当有正式的测试用例要测试时。

8
在不进行广泛模拟的情况下,应该如何编写单元测试?
据我了解,单元测试的重点是隔离测试代码单元。这意味着: 它们不应被代码库中其他地方不相关的代码更改破坏。 与集成测试相反(集成测试可能会中断),只有一个单元测试应该通过被测试单元中的错误来破坏。 所有这些暗示着,应该模拟掉测试单元的所有外部依赖关系。我的意思是所有外部依赖关系,而不仅仅是网络,文件系统,数据库等“外部层”。 这得出一个合理的结论,几乎每个单元测试都需要模拟。另一方面,谷歌对嘲笑的快速搜索显示了成千上万的文章声称“嘲笑是一种代码味道”,应该(尽管不完全)避免。 现在,到问题。 单元测试应如何正确编写? 它们和集成测试之间的界线到底在哪里? 更新1 请考虑以下伪代码: class Person { constructor(calculator) {} calculate(a, b) { const sum = this.calculator.add(a, b); // do some other stuff with the `sum` } } 可以在Person.calculate不模拟Calculator依赖关系的情况下测试该方法的测试(假定,它Calculator是不访问“外部世界”的轻量级类)可以视为单元测试吗?

11
严格出于测试目的修改代码是否是错误的做法
我与一名程序员同事讨论关于仅修改一段可工作的代码以使其可测试(例如通过单元测试)是好是坏的做法。 我的观点是,在保持良好的面向对象和软件工程实践的范围内(当然不要“公开一切”等),这是可以的。 我同事的观点是,仅出于测试目的修改代码(有效)是错误的。 只是一个简单的示例,请考虑某些组件(用C#编写)使用的这段代码: public void DoSomethingOnAllTypes() { var types = Assembly.GetExecutingAssembly().GetTypes(); foreach (var currentType in types) { // do something with this type (e.g: read it's attributes, process, etc). } } 我建议可以修改此代码以调出另一个可以完成实际工作的方法: public void DoSomething(Assembly asm) { // not relying on Assembly.GetExecutingAssembly() anymore... } 此方法接受一个Assembly对象进行处理,从而可以通过您自己的Assembly进行测试。我的同事认为这不是一个好习惯。 什么被认为是良好且常见的做法?

9
我们可以在测试软件时假设用户不会对软件执行此类愚蠢的操作吗?
例如:在Web应用程序中执行表单的功能测试时,我们将通过输入不同种类的随机输入值来测试字段。 通常,作为Web应用程序的用户,我们实际上并未在字段中输入随机值。 那么,当生产中出现此类问题的可能性较小时,合并所有可能/可能不会导致错误的测试用例有什么用呢? 注意:上面的示例仅是示例案例;此类问题可能发生在任何种类的功能/模块中。 我问这个问题只是为了知道是否要遵循任何标准做法,或者它完全取决于产品,领域和所有其他因素。

17
在诊断和修复缺陷之前坚持重现每个缺陷是否合理?
我在一家软件产品公司工作。我们拥有实施我们产品的大型企业客户,我们为他们提供支持。例如,如果有缺陷,我们会提供补丁等。换句话说,这是一个非常典型的设置。 最近,针对客户在日志文件中发现的与我方产品的集群实现中的并发数据库访问有关的异常,已发出并分配了票证给我。因此,此客户的特定配置对于此错误的发生可能很关键。我们从客户那里得到的只是他们的日志文件。 我向我的团队建议的方法是尝试在类似于客户的配置设置中重现该错误并获得可比的日志。但是,他们不同意我的方法,即我不需要重现该错误,因为该错误过于耗时,并且需要在VM上模拟服务器集群。我的团队建议我只是“遵循代码”以查看线程和/或事务不安全代码的位置,然后将更改放入简单的本地开发工作中,而不是像发生事件的环境那样的集群实现错误的来源。 对我来说,要制定一个抽象的蓝图(程序代码)而不是一个有形的,可见的表现形式(运行时再现)似乎很困难,所以我想问一个普遍的问题: 在诊断和修复缺陷之前坚持重现每个缺陷并对其进行调试是否合理? 要么: 如果我是高级开发人员,我是否应该能够阅读多线程代码并对其在所有用例场景中的工作情况有一个清晰的了解,而不是需要运行应用程序,亲自测试不同的用例场景并逐步完成代码一行一行?还是我对这种工作环境的要求很差? 调试sissies吗? 我认为,响应事故单提交的任何修复程序都应在模拟的环境中进行测试,该环境应尽可能接近原始环境。您还怎么知道它将真正解决该问题?这就像发布一款新车型时一样,没有用假人对它进行碰撞测试即可证明安全气囊确实有效。 最后但并非最不重要的一点,如果您同意我的看法: 我应该如何与我的团队交谈,以说服他们我的方法是合理,保守和防弹的?

16
当TDD没有帮助时,如何避免代码中的逻辑错误?
最近,我正在编写一小段代码,以人类友好的方式指示事件的年代。例如,它可能表明该事件发生在“三周前”或“一个月前”或“昨天”。 需求相对明确,这是测试驱动开发的完美案例。我一个接一个地编写了测试,实现了通过每个测试的代码,一切似乎都正常运行。直到生产中出现错误为止。 这是相关的代码段: now = datetime.datetime.utcnow() today = now.date() if event_date.date() == today: return "Today" yesterday = today - datetime.timedelta(1) if event_date.date() == yesterday: return "Yesterday" delta = (now - event_date).days if delta < 7: return _number_to_text(delta) + " days ago" if delta < 30: weeks = math.floor(delta / 7) …

11
路径覆盖范围是否可以保证找到所有错误?
如果测试了程序的每条路径,是否可以保证找到所有错误? 如果没有,为什么不呢?如何解决程序流程的每一种可能的组合,如果存在的话却找不到问题? 我毫不犹豫地建议可以找到“所有错误”,但这也许是因为路径覆盖不切实际(因为它是组合的),所以从未经历过? 注意:本文提供了我考虑的覆盖类型的快速摘要。

7
使用验收和集成测试代替单元测试是否足够?
这个问题的简短介绍。我现在已经使用TDD,最近使用BDD已经超过一年了。我使用诸如嘲笑之类的技术来更有效地编写测试。最近,我开始了一个个人项目,为自己编写一个小小的资金管理程序。由于我没有遗留代码,因此从TDD开始是一个完美的项目。不幸的是,我没有体验到TDD的喜悦。它甚至破坏了我的乐趣,以至于我放弃了这个项目。 怎么了 好吧,我使用了类似TDD的方法来使测试/需求发展程序的设计。问题在于,超过一半的开发时间用于编写/重构测试。所以最后我不想实现任何其他功能,因为我需要重构并编写许多测试。 在工作中,我有很多遗留代码。在这里,我写了越来越多的集成和验收测试,以及更少的单元测试。这似乎不是一个坏方法,因为大多数错误是通过验收和集成测试检测到的。 我的想法是,最终我可以编写比单元测试更多的集成和验收测试。就像我说的那样,对于检测错误,单元测试并不比集成/验收测试好。单元测试也对设计有益。由于我曾经写过很多文章,所以我的类总是被设计为可测试的。此外,在大多数情况下,让测试/需求指导设计的方法可导致更好的设计。单元测试的最后一个优点是它们更快。我已经写了足够多的集成测试,知道它们可以和单元测试一样快。 在浏览网络后,我发现这里和那里提到的想法非常相似。您如何看待这个想法? 编辑 在一个例子中回答这个设计很好的例子,但是我需要对下一个需求进行大量重构: 首先,执行某些命令有一些要求。我编写了一个可扩展的命令解析器-从某种命令提示符下解析命令,并在模型上调用正确的命令。结果以视图模型类表示: 这里没有错。所有类都彼此独立,我可以轻松添加新命令,显示新数据。 下一个要求是,每个命令应具有其自己的视图表示形式-命令结果的某种预览。我重新设计了程序,以针对新要求实现更好的设计: 这也很好,因为现在每个命令都有自己的视图模型,因此也有自己的预览。 事实是,命令解析器已更改为使用基于令牌的命令解析,并且剥夺了其执行命令的能力。每个命令都有自己的视图模型,数据视图模型只知道当前的命令视图模型,而不知道必须显示的数据。 我现在想知道的是,新设计是否没有违反任何现有要求。我不必更改任何我的验收测试。我不得不重构或删除几乎每个单元测试,这是一大堆工作。 我想在这里展示的是在开发过程中经常发生的一种常见情况。旧的或新的设计都没有问题,它们只是随需求而自然变化-我的理解是,TDD的优点之一就是设计不断发展。 结论 感谢您的所有答案和讨论。在此讨论的总结中,我想到了一种方法,将在下一个项目中对其进行测试。 首先,我在像往常一样执行任何操作之前编写所有测试。 对于需求,我首先编写一些验收测试,以测试整个程序。然后,我为需要实现需求的组件编写了一些集成测试。如果有一个组件与另一个组件紧密协作以实现此要求,那么我还将编写一些集成测试,其中两个组件都需要一起测试。最后但并非最不重要的一点是,如果我必须编写一个具有高排列的算法或任何其他类(例如,序列化程序),我将为此特定类编写单元测试。所有其他类均未经测试,但未经任何单元测试。 对于错误,可以简化过程。通常,错误是由一个或两个组件引起的。在这种情况下,我将为测试该错误的组件编写一个集成测试。如果它与算法有关,我只会编写一个单元测试。如果不容易检测到发生错误的组件,我将编写验收测试以查找错误-这应该是一个例外。

7
在设计可测试性时如何处理静态实用程序类
我们正在尝试将我们的系统设计为可测试的,并在大多数零件中使用TDD进行开发。当前,我们正在尝试解决以下问题: 在各个地方,我们有必要使用静态辅助方法,例如ImageIO和URLEncoder(均为标准Java API)以及各种其他主要由静态方法组成的库(例如Apache Commons库)。但是,测试使用此类静态帮助程序类的方法极其困难。 我有一些解决此问题的想法: 使用可以模拟静态类的模拟框架(例如PowerMock)。这可能是最简单的解决方案,但感觉有点像放弃。 围绕所有这些静态实用程序创建实例化包装器类,以便可以将它们注入使用它们的类中。这听起来像是一个相对干净的解决方案,但是我担心我们最终将创建大量这些包装器类。 将对这些静态帮助器类的每个调用提取到一个可以重写的函数中,并测试我实际要测试的类的子类。 但是我一直认为这只是许多人在进行TDD时必须面对的问题-因此必须已经有解决此问题的方法。 使使用这些静态帮助器的类可测试的最佳策略是什么?

19
编译器为何如此可靠?
我们每天都在使用编译器,就像它们的正确性一样,但是编译器也是程序,并且可能包含错误。我一直想知道这种可靠的鲁棒性。您是否曾经在编译器中遇到错误?这是什么,您如何意识到问题出在编译器本身? ...怎么做他们让编译器非常可靠?

10
我们应该测试所有方法吗?
所以今天我和队友讨论了单元测试。当他问我“嘿,那堂课的考试在哪儿,我只看到一个?”时,整个事情开始了。整个类都是一个管理器(或服务,如果您喜欢这样称呼它),几乎所有方法都只是将东西委托给DAO,所以它类似于: SomeClass getSomething(parameters) { return myDao.findSomethingBySomething(parameters); } 一种没有逻辑的样板(或者至少我不认为像逻辑这样的简单委托),但是在大多数情况下(层分离等)很有用。我们进行了相当长时间的讨论,是否应该对它进行单元测试(我认为值得一提的是,我对DAO进行了完全单元测试)。他的主要论据是(显然)它不是TDD,并且有人可能希望查看测试以检查此方法的作用(我不知道它怎么可能更明显),或者将来有人可能希望更改该方法。实现并向其中添加新的(或更多类似“ any”的)逻辑(在这种情况下,我猜有人应该只测试该逻辑)。 不过,这让我思考。我们应该争取最高的测试覆盖率吗?还是仅仅是出于艺术的缘故?我根本看不出在进行以下测试之后有任何原因: getter和setter(除非他们实际上有一些逻辑) “样板”代码 显然,对这种方法(带有模拟)的测试将花费我不到一分钟的时间,但我想这仍然是浪费时间,并且每个CI都需要花费一毫秒以上的时间。 是否有任何合理/不“易燃”的理由来说明为什么要测试每一行(或尽可能多的行)代码?

9
开发人员还应该充当测试人员吗?[关闭]
我们是一个由3个开发人员,1个设计师,1个Scrum管理员和1个产品所有者组成的Scrum团队。但是,我们的团队中没有官方测试人员。我们一直面临的问题是,测试应用程序并通过这些测试并消除错误已被视为考虑完成PBI(产品待办事项)的标准之一。 但是问题在于,无论我们(3位开发人员和1位设计师)尝试测试应用程序和已实现的用例的多少,仍然看不到一些错误,并且破坏了向利益相关者的展示(墨菲定律)。 作为补救措施,我们建议公司雇用新的测试人员。工作的人只能进行测试,并且只能进行测试。官方专业测试人员。 但是,问题在于,Scrum负责人和利益相关者认为开发人员(或设计师)也应该是测试人员。 对吗 我们开发人员(还是设计师)也应该成为测试人员吗?
60 testing  scrum 

2
为我不明白目的的代码编写测试
我最近完成了黑盒重构。我无法检入它,因为我无法确定如何进行测试。 在较高的层次上,我有一个其初始化涉及从某些类B获取值的类。如果类B为“空”,它将生成一些合理的默认值。我将这一部分提取到一种方法中,该方法将B类初始化为相同的默认值。 我还没有弄清这两个类的目的/背景,或如何使用它们。因此,我无法从空的类B初始化对象并检查其是否具有正确的值/是否做正确的事情。 我最好的主意是运行原始代码,根据初始化的成员在公共方法的结果中进行硬编码,然后对此进行测试。我不太清楚为什么我对这个想法含糊不清。 这里有更好的进攻方式吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.