18

问题

我想这是一个很常见的问题。添加新代码会转化为回归——现有的测试用例会过时。代码中的依赖意味着即使你知道如何修复这个特定的回归,在两个方向上的 n 多个地方也可能存在间接回归 - 传入和传出。

要求

我有一家运行 SVN、Maven+Nexus、Sonar、Jenkins 和 JIRA、QC、QTP 的商店。总而言之,一个良好的 CI 环境。

随着每一个新的构建,我都会有新的回归案例。我想在两个方向上找到 Java 包依赖关系并正确更新测试用例,以涵盖所有类型的回归——直接和间接。这更是一个问题,因为我的单元测试覆盖率甚至没有接近 50%,而且集成测试的自动化跟不上开发的步伐。

我的选择

  1. 声纳
  2. 谷歌代码Pro
  3. 建筑师
  4. Jtest(与供应商 Parasoft 进行了讨论。他们没有用于此的工具)
  5. 利用我现有的环境,比如说,一个Atlassian插件
  6. Kalisitck(供应商演示 - 不错的工具 - 涉及学习曲线和成本)
  7. Coverity(像 Kalistick - 学习曲线和复杂的安装。非常昂贵的许可证。
  8. 任何其他开源/付费?

JArchitect、SONAR 和 CodePro 将为您提供一个类似thisthis的简单矩阵。通过告诉我哪些用户使用的类受到影响,这满足了我的一半要求。我想要的是更进一步,让工具告诉我哪些相应的测试用例受到影响,以及我是否需要更新和/或执行它们以覆盖我的回归风险。

Kalistick、Coverity 和其他人可能会做我想做的事 - 它们的设置和配置很繁重,随着您的系统缓慢增长,因此不能立即产生生产力,需要成本并且需要学习曲线。

简短的问题

考虑到安装、学习曲线、成本、可用性或任何其他参数等所有因素,在我的设置中使用哪些工具。



我已经阅读了关于Java 的静态分析工具推荐这样的线程很少?, https://stackoverflow.com/questions/3716203/automatic-code-quality-and-architecture-quality-static-code-analysis代码度量的魅力是什么? 和许多相关的,但他们没有回答我的具体问题。

4

7 回答 7

2

您可以通过跟踪它们接触的代码来确定哪些测试是相关的。您可以使用测试覆盖率工具跟踪他们接触的代码。

大多数测试覆盖工具构建了一组显式的运行测试执行的位置。这就是“覆盖”的意义所在。如果您组织测试运行以一次执行一个单元测试,然后拍摄覆盖率数据的快照,那么您就知道每个测试涵盖了哪些代码。

修改代码时,您可以确定修改后的代码的交集以及单个测试涵盖的内容。如果交叉点非空,您肯定需要再次运行该测试,并且可能需要更新它。

使这项工作存在几个实际问题。

首先,通常很难弄清楚测试覆盖工具是如何记录这些定位数据的。其次,您必须让测试机制在每个测试的基础上捕获它;这可能难以组织,和/或覆盖数据可能难以提取和存储。第三,您需要计算测试中“修改的代码”与“覆盖的代码”的交集;这在抽象上很大程度上是一个与大位向量相交的问题。最后,捕获“代码修改”有点棘手,因为有时代码会移动;如果测试了文件中的位置 100,并且行在文件中移动,您可能无法获得可比较的位置数据。这将导致误报和误报。

有一些测试覆盖率工具可以以易于捕获的形式记录覆盖率数据,并可以进行计算。确定代码更改比较棘手;您可以使用 diff,但移动的代码会使问题有些混乱。您可以找到比较代码结构的差异工具,这些工具可以识别此类移动,因此您可以获得更好的答案。

如果您有源代码切片器,则可以计算测试的输出如何(向后切片)依赖于输入;显然,该切片中的所有代码都会影响测试。我认为这里的坏消息是这样的切片机并不容易获得。

于 2013-01-09T03:40:29.800 回答
2

你能为你的问题找到的最好的工具实际上不是一个工具,而是一个实践。我强烈建议您阅读有关测试驱动开发的内容(请参阅Lasse Koskela 的书)和示例规范(请参阅Gojko Adzic 的书,它们很棒)。

使用这些做法将从根本上改变两件事:

  1. 您将拥有接近 100% 的测试覆盖率
  2. 测试将成为一等公民,并将成为您代码的中心点

我发现这与您的问题相关的原因是您的场景暗示了测试的完全相反的作用:人们将在代码中执行更改,然后他们会想“哦,不......现在我必须弄清楚我在那些该死的测试中打破了什么”。

根据我的经验,不应忽视测试或将其视为“低级代码”。虽然我的回答指出了从长远来看只会产生明显结果的方法变化,但它可能有助于在未来完全避免这个问题。

于 2013-01-07T09:11:15.583 回答
2

我本人是 Sonar 的忠实粉丝,因为您已经在运行它并在您的 CI 环境中工作,这将是我的建议。我不太确定 Sonar 的 Dependency Cycle Matrix 是如何做到你想要的,或者更确切地说是你想要的。

于 2013-01-04T08:52:12.047 回答
2

您可以使用Classycle-Dependency Checker找到最高级别的依赖项。指南中的“检查类依赖关系”部分可能会对您的情况有所帮助。然而,通常使用静态分析工具,我们分析源代码库(例如:Project->src 目录)或测试代码库(例如:Project->test 目录),但不能同时分析两者。但在您的情况下,您似乎也想找出源代码和测试代码之间的依赖关系。因此,通过提供输入路径作为 src 和 test 的父路径(例如:项目根目录)来执行适当的依赖关系分析工具可能是您需要的(例如:使用依赖关系找出 -> 如果源 X 发生变化,什么测试中的依赖类会受到该更改的影响)。

于 2013-01-05T17:23:05.417 回答
2

如果我正确阅读了这个问题,您需要一个分析源代码并确定哪些测试不需要重新运行的工具。

首先要考虑的是始终运行所有测试有什么问题?这就是 CI 的意思。如果您无法在 15 分钟内运行所有单元测试并且无法在一夜之间运行所有集成/压力测试,请解决导致这种情况的任何问题,可能通过购买一些硬件来解决。

如果做不到这一点,唯一可以跟踪潜在测试回归的是覆盖率分析(例如http://www.eclemma.org/)。即使是基本的 OO 设计,更不用说依赖注入了,静态包或类依赖充其量是没有意义的,并且可能会积极误导,就哪些更改可能导致哪些测试失败而言。这忽略了问题是 A 应该调用 B 而不是的情况。但是,交叉引用更改的文件与调用的文件,如果没有交叉点,则可能不重新运行测试是安全的 - 剩余的失败将是一些代码添加一个以前没有的事件处理程序之类的事情。

我认为没有免费的工具可以做到这一点,但它应该可以从 Jenkins/Emma/Git 编写脚本。或者使用 Kalistick 等集成解决方案之一。但我怀疑它能否有效地击败基于与开发团队沟通的人类判断,了解他们正在尝试做什么

在一个模糊的相关说明中,Java 世界实际需要但不存在的简单工具是 junit 的扩展,它按依赖顺序运行一组测试,并在第一个错误时停止。这将提供一点额外帮助,让开发人员专注于最可能的回归源。

于 2013-01-04T13:00:11.703 回答
2

一些可能有帮助的工具。请注意,并非所有这些都与 CI 集成。

iPlasma是一个很棒的工具

CodePro是一个 Eclipse 插件,它有助于检测代码和设计问题(例如重复的代码、破坏封装的类或放置在错误类中的方法)。(现在被谷歌收购)

Relief是一种可视化 Java 项目的以下参数的工具: 包的大小,即它包含多少类和接口 被可视化的项目的种类(包和类表示为框,接口和类型的字段表示为球体)。正在使用的项目的重量(表示为重力,即中心距离)依赖项的数量(表示为深度)。

Stan4j是一个售价几百美元的商业工具。它仅针对 Java 项目,非常接近(或比报告更好一点?不确定)Sonar。它具有良好的 Eclipse 集成。

Intellij 依赖分析

从您的问题中我可以理解的是 - 您需要跟踪两个 OO 指标 - Efferent Coupling (Ca)和Afferent Couplings (Ce)。有了这个,您可以缩小到所需的包。您可以探索编写 Eclipse 插件的机会,该插件在每次构建时都可以突出显示基于 Ca、Ce 指标的所需类。

于 2013-01-07T12:11:46.257 回答
2

使用JDepend,您可以分析包之间的依赖关系,甚至可以创建单元测试来确保依赖关系,或者将其与Fitnesse集成以获得良好的依赖关系表测试。如果您的测试在特定的包中,这可能会有所帮助......

于 2013-01-03T09:48:16.710 回答