Questions tagged «unit-testing»

单元测试是一种测试源代码的各个单元以确定它们是否适合使用的方法。

3
何时给定(GWT)和行为安排断言(AAA)之间的区别?
在TDD中,有Arrange Act Assert(AAA)语法: [Test] public void Test_ReturnItemForRefund_ReturnsStockOfBlackSweatersAsTwo_WhenOneInStockAndOneIsReturned() { //Arrange ShopStock shopStock = new ShopStock(); Item blackSweater = new Item("ID: 25"); shopStock.AddStock(blackSweater); int expectedResult = 2; Item blackSweaterToReturn = new Item("ID: 25"); //Act shopStock.ReturnItemForRefund(blackSweaterToReturn); int actualResult = shopStock.GetStock("ID: 25"); //Assert Assert.AreEqual(expectedResult, actualResult); } 在BDD中,编写测试使用类似的结构,但语法为“当下(GWT)”: [Given(@"a customer previously bought a black sweater …
13 c#  unit-testing  tdd  bdd 

5
破旧/旧版单元测试
我在一家大公司工作,负责一个带有数千个junit测试的大型Java应用程序。自从我担任这个职位以来,已经有200到300个失败的测试(可能是多年失败的测试)。这些测试既旧又脆弱,并且杂乱无章,通常以实时沙盒数据结尾。 我的目标是100%通过测试,这样我们就可以打破单元测试失败的基础,但是直到解决了失败的测试之后我才能做到。我的预算很少,因为维护预算主要用于支持,但是我的团队已经确定并修复了低挂的水果测试(主要是配置/本地资源问题),而我们的测试只有30-40个非常丑陋。 对最佳实践有何看法?我认为测试不是有价值的,但是我也不知道他们正在测试什么,或者为什么他们不钻研就无法工作,这需要我们花费很多时间和金钱。 我想我们应该用我们知道的任何东西记录破损测试的状态,然后完全删除或忽略破损测试,并输入一个较低优先级的错误/工作项来调查和修复它们。然后,我们将达到100%的水平,并开始从其他测试中获得真正的价值,如果我们有维护/重构的意外之财,我们将能够再次进行选择。 最好的方法是什么? 编辑:我认为这是一个不同于该问题的问题,因为我对我们应该编写的测试有明确的方向,但是我继承了遗留失败的测试,以便在当前的大量测试变得有意义之前解决这些问题。

3
在某些情况下如何引起程序员的注意?
让我们从一个例子开始。 比方说,我有一个称为方法export,该方法在很大程度上取决于数据库架构。“严重依赖”是指我知道(经常)向特定表中添加新列会导致相应的export方法更改(通常也应将新字段也添加到导出数据中)。 程序员通常会忘记更改export方法,因为还不清楚您是否应该看一下。我的目标是迫使程序员明确决定是否要忘记查看该export方法还是只是不想在导出数据中添加字段。我正在寻找针对此问题的设计解决方案。 我有两个想法,但它们都有缺陷。 智能的“阅读所有”包装 我可以创建智能包装器,以确保显式读取所有数据。 像这样: def export(): checker = AllReadChecker.new(table_row) name = checker.get('name') surname = checker.get('surname') checker.ignore('age') # explicitly ignore the "age" field result = [name, surname] # or whatever checker.check_now() # check all is read return result 因此,checker断言if是否table_row包含另一个未读取的字段。但是,所有这些东西看起来有点沉重,并且(可能)会影响性能。 “检查该方法”单元测试 我可以创建一个能够记住最后一个表模式的单元测试,并且每次更改表时都会失败。在那种情况下,程序员会看到类似“不要忘了检查export方法”的信息。要隐藏警告程序员,可以(或不会-这是一个问题)签出export并手动(这是另一个问题)通过在其中添加新字段来修复测试。 我还有其他一些想法,但是它们太难实现或难以理解(我不希望该项目成为难题)。 上面的问题只是我不时遇到的更多问题的一个示例。我想绑定一些代码和/或基础结构,因此更改其中的一个代码会立即提醒程序员检查另一个代码和/或基础结构。通常,您有一些简单的工具,例如提取通用逻辑或编写可靠的单元测试,但是我正在寻找更复杂情况的工具:也许我现在知道一些设计模式。

4
模拟是否违反开放/封闭原则?
前段时间,我在找不到的Stack Overflow答案上读了一句话,该句子解释您应该测试公共API,而作者说您应该测试接口。作者还解释说,如果更改了方法实现,则无需修改测试用例,因为这样做会破坏确保被测系统正常工作的契约。换句话说,如果方法不起作用,则测试应该失败,但这不是因为实现发生了变化。 当我们谈论嘲笑时,这引起了我的注意。由于模拟在很大程度上依赖于被测系统依赖项的期望调用,因此模拟与实现紧密相关,而不是与接口紧密相关。 在研究模拟与存根时,有几篇文章认为应该使用存根而不是模拟,因为它们不依赖于依赖项的期望,这意味着测试不需要了解测试实施中的基础系统。 我的问题是: 模拟是否违反开放/封闭原则? 在上一段中支持存根的论点中是否缺少某些内容,使存根与模拟不那么好? 如果是这样,什么时候可以模拟一个好用例,什么时候可以使用存根?

5
如何进行一项测试取决于另一项测试的结果?
假设有一个实用程序类,提供了许多其他类在代码中各处使用的一些常见静态方法。 您将如何为实用程序的使用者设计单元测试,以便在任何一项实用程序测试未通过的情况下使他们的测试失败?您可以这样做还是必须自己检查实用程序类测试是否全部为绿色? 例如,我有一个消息拆分器实用程序,它由消息解析器使用(或更确切地说,它的输出)。我想确保在测试邮件解析器之前,邮件拆分器能够正常工作。 我已经为它们两个编写了测试,但是有没有办法链接它们并使一个测试依赖于其他测试的结果? 我找不到适合的标签,但是我使用的是Visual Studio的单元测试引擎。

4
通过这种方式,我编写此代码是可测试的,但是我缺少它吗?
我有一个名为的界面IContext。出于此目的,除了以下内容外,它的作用并不重要: T GetService<T>(); 该方法的作用是查看应用程序的当前DI容器,并尝试解决依赖关系。我认为还算标准。 在我的ASP.NET MVC应用程序中,我的构造函数如下所示。 protected MyControllerBase(IContext ctx) { TheContext = ctx; SomeService = ctx.GetService<ISomeService>(); AnotherService = ctx.GetService<IAnotherService>(); } 因此,我不是在为每个服务的构造函数中添加多个参数(因为这对于扩展应用程序的开发人员来说确实很烦人和耗时),而是使用此方法来获取服务。 现在,感觉不对。但是,我目前在脑海中证明它的方式是这样- 我可以嘲笑它。 我可以。模拟IContext测试控制器并不难。无论如何,我必须: public class MyMockContext : IContext { public T GetService<T>() { if (typeof(T) == typeof(ISomeService)) { // return another mock, or concrete etc etc } // etc …

1
游戏测试策略
我继承了一个基于网络的教育游戏。在过去的一年中,我一直致力于稳定代码和添加新功能。大多数逻辑都在前端,因此后端单元测试虽然很有用,但只覆盖了一小部分代码。 游戏已经到了开始变得复杂的地步。每个游戏有两种不同的模式,并且游戏的行为取决于模式。还有各种影响游戏玩法的标志。 我担任应用程序开发人员已有10多年了,这使我感到困惑。在企业界,算法始终以相同的方式起作用。我将为算法编写一个单元测试,我期望值42,如果我没有得到该值,它将出错。 说到游戏,我迷路了。我该如何测试?我有可用的测试仪。我可以花时间编写单元测试。 测试人员...不可靠。他们不是最能根除问题的人,我也没有给他们最好的方向。在每个发行周期花大量时间测试游戏的每个排列和组合时,我应该如何将它们用作资源? 单元测试似乎很有限。由于大多数逻辑是javascript(并且我继承了意大利面条代码),因此我可以使用诸如Cucumber或selenium之类的前端套件来确保某些功能正常工作。 那是最好的策略吗?游戏公司如何测试游戏? 我已经读过“ 复杂游戏的测试驱动开发 ”(以及网站上的其他问题)的问题,但是它没有解决我所寻找的问题。我要的是策略,而不是具体的测试示例。

5
根据有用性进行单元测试的类型
从价值的角度来看,我在实践中看到两组单元测试: 测试一些非平凡逻辑的测试。(在实现之前或之后)编写它们会发现一些问题/潜在错误,并有助于您确定将来逻辑发生变化时的情况。 测试一些非常琐碎的逻辑的测试。这些测试比测试代码更像文档代码(通常带有模拟)。这些测试的维护工作流不是“某些逻辑改变了,测试变成了红色-感谢上帝,我编写了这个测试”,而是“一些琐碎的代码改变了,测试变成了假否定-我必须维护(重写)该测试而没有获得任何收益” 。在大多数情况下,这些测试不值得维护(出于宗教原因除外)。根据我在许多系统中的经验,这些测试占所有测试的80%。 我正在尝试找出其他人对单元测试按值分离以及如何与我的分离相对应的想法。但是我最常看到的是全职TDD宣传或测试都是无用的,只是编写代码宣传。我对中间的东西感兴趣。欢迎您发表自己的想法或参考文章/论文/书籍。
13 unit-testing  tdd 

2
从被测系统中提取类时,应该重构单元测试吗?
我写的这个类做了几件事(也许这违反了单一责任原则)。我现在该项目的其他部分需要意识到一块是逻辑的,我要揭露它是提取的一类了我原来的被测系统的方式。 我期望无需更改任何测试代码即可执行此操作,但是当我完成操作时,您可能会说该测试不再是单元测试。它将测试原始类和我提取的类。换句话说,我将有一个测试用例,但有两个系统正在测试中。 完成后是否应该重构测试代码?IE:创建一个ExtractedClassTest并将所有相关测试从OriginalClassTest移入其中?这似乎有点冒险:我可能会在此过程中失去一些覆盖面,它可能不像移动测试那样简单,并且我最终会重写一些我知道曾经可以使用但无法再使用的测试代码,等等 另一方面,如果按原样保留OriginalClassTest,则可以看到这是测试维护问题。找到ExtractedClass的测试在哪里会有些混乱。您的第一印象将是它不存在。随着时间的推移,随着大量生产代码的重构,这可能会成为一个严重的问题。 我是TDD的新手,所以我需要专家的建议。谢谢!

3
使用单元测试讲故事是个好主意吗?
因此,我有一段时间前编写的身份验证模块。现在,我看到了自己的错误并为此编写了单元测试。在编写单元测试时,我很难想出好名字和好地方进行测试。例如,我有类似的东西 需要Login_should_redirect_when_not_logged_in 需要登录时登录_通过_登录_登录 Login_should_work_when_given_proper_credentials 就个人而言,即使看起来“适当”,我还是觉得它有点丑陋。我也难以通过仅扫描测试来区分测试(我必须至少读取两次方法名称才能知道失败了)。 因此,我认为也许不编写纯粹测试功能的测试,而是编写一组涵盖场景的测试。 例如,这是我想出的一个测试存根: public class Authentication_Bill { public void Bill_has_no_account() { //assert username "bill" not in UserStore } public void Bill_attempts_to_post_comment_but_is_redirected_to_login() { //Calls RequiredLogin and should redirect to login page } public void Bill_creates_account() { //pretend the login page doubled as registration and he made an …

1
包装第三方代码是否是对用户进行单元测试的唯一解决方案?
我正在进行单元测试,并且在我的一个类中,我需要从一种方法中发送邮件,因此使用构造函数注入,我将注入Zend_MailZend框架中的类的实例。 现在有人认为,如果一个库足够稳定并且不会经常更改,那么就无需对其进行包装。因此,假设这Zend_Mail是稳定的并且不会改变并且完全满足我的需求,那么我就不需要包装器了。 现在看一下我的课程Logger,该课程取决于Zend_Mail: class Logger{ private $mailer; function __construct(Zend_Mail $mail){ $this->mail=$mail; } function toBeTestedFunction(){ //Some code $this->mail->setTo('some value'); $this->mail->setSubject('some value'); $this->mail->setBody('some value'); $this->mail->send(); //Some } } 但是,单元测试要求我一次测试一个组件,因此我需要模拟Zend_Mail该类。另外,我违反了依赖倒置原则,因为我的Logger课程现在依赖于具体而非抽象。 现在,我如何Logger在不进行包装的情况下进行隔离测试Zend_Mail? 该代码在PHP中,但不一定必须提供答案。这更多的是设计问题,而不是特定于语言的功能

5
单元测试程序代码有效吗?
在当前的项目中,希望将单元测试纳入我们的开发周期,以避免似乎不断渗入我们的代码中的错误数量。问题在于,意大利面条代码的程序化程度为95%,我从来没有使用过单元测试(我所有的单元测试经验都使用过OOP代码) 因此,我的问题简而言之是用我们当前的代码库进行单元测试,还是建议将其推迟到将应用程序迁移到适当的OOP框架后才是明智的选择? PS:当我尝试将这个问题的样式与语言无关时,我认为说明所涉及的应用程序使用PHP和javascript将有助于提供更具体的答案,从而可以回答该问题,因为从经验来看,此类应用程序大多会发生这种情况。

8
检查失败的单元测试的价值是什么?
尽管有阻止执行单元测试的方法,但是检查失败的单元测试的价值是什么? 我将使用一个简单的示例:区分大小写。当前代码区分大小写。该方法的有效输入是“ Cat”,它将返回Animal.Cat的枚举。但是,该方法的所需功能不应区分大小写。因此,如果所描述的方法通过“ cat”传递,则它可能返回类似于Animal.Null而不是Animal.Cat的内容,并且单元测试将失败。尽管只需进行简单的代码更改即可完成此工作,但更复杂的问题可能需要花费数周的时间才能解决,但是使用单元测试来确定错误可能不是那么复杂。 当前正在分析的应用程序具有4年有效的代码。但是,最近有关单元测试的讨论发现了代码中的缺陷。有些只需要显式的实现文档(例如是否区分大小写),或者不根据当前调用方式执行该错误的代码。但是可以执行特定的场景来创建单元测试,这将导致错误被看到并且是有效的输入。 在有人能够修正该代码之前,检查行使该错误的单元测试的价值是什么? 是否应该使用忽略,优先级,类别等标记此单元测试,以根据执行的测试确定构建是否成功?最终,一旦有人对其进行了修复,就应该创建单元测试来执行代码。 一方面,它表明已识别的错误尚未修复。另一方面,在日志中可能会出现数百个失败的单元测试,并且很难找出应该失败的测试与由于代码检入而导致的失败。


4
当TDD测试显示需要进行测试的新功能时该怎么办?
当您编写测试并达到需要通过测试并意识到需要附加功能的时候,该怎么做?该新功能也需要进行测试,但是TDD周期表示“使测试失败,使其通过然后进行重构”。如果我要通过测试,那我就不应该继续进行另一个失败的测试来测试我需要实现的新功能。 例如,我正在编写一个具有函数WillCollideWith(LineSegment)的点类: public class Point { // Point data and constructor ... public bool CollidesWithLine(LineSegment lineSegment) { Vector PointEndOfMovement = new Vector(Position.X + Velocity.X, Position.Y + Velocity.Y); LineSegment pointPath = new LineSegment(Position, PointEndOfMovement); if (lineSegment.Intersects(pointPath)) return true; return false; } } 当我意识到我需要LineSegment.Intersects(LineSegment)函数时,我正在为CollidesWithLine编写测试。但是,我是否应该停止测试周期中的工作以创建此新功能?这似乎违反了“红色,绿色,重构”原则。 我是否应该只编写检测到lineSegments在CollidesWithLine函数内部相交并在工作后对其进行重构的代码?在这种情况下,这是可行的,因为我可以从LineSegment访问数据,但是如果这种数据是私有的,那该怎么办?
13 unit-testing  tdd 

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.