章节目录:
通用
如何在命令行快速访问有关使用方法的信息?
使用 -help
命令行选项:
jtestcli.exe -help
如何通过代理使用 Jtest?
使用系统代理设置
要让 Jtest 使用系统代理设置,需使用 -D
命令行选项配置 java.net.useSystemProxies=true
。
如果您的代理服务器要求进行身份验证,则可以使用 parasoft.https.systemProxyUser=[用户名]
和parasoft.https.systemProxyPassword=[密码,可由 Parasoft 加密]
属性配置您的凭据。需为每个协议分别指定用户和密码。
您的命令行可能与以下内容类似:
java -Djava.net.useSystemProxies=true -Dparasoft.https.systemProxyUser=user -Dparasoft.https.systemProxyPassword=password
使用手动代理设置
要使用手动设置通过代理服务器进行连接,需要将协议专用的系统属性传递给 JVM(使用 -D
命令行选项)来配置连接。要与 Jtest 一起使用,应确保配置 HTTPS 协议的系统属性。至少,您必须配置 https.proxySet=true
、https.proxyHost=[hostname]
和 https.proxyPort=[port number]
。如果代理服务器要求身份验证,则可以使用 https.proxyUser
和 https.proxyPassword
属性。
您的命令行可能与以下内容类似:
java -Dhttps.proxySet=true -Dhttps.proxyHost=myserver.example.com -Dhttps.proxyPort=8080 -Dhttps.proxyUser=user1 -Dhttps.proxyPassword=MyPassword
此外,您还可以配置 https.nonProxyHosts
属性来指定不需要通过代理连接的主机。
如果您在 Eclipse 或 IntelliJ IDEA 中使用桌面版 Jtest,Jtest 能够自动检测并使用 Eclipse 或 IntelliJ IDEA 中指定的代理设置。不需要额外的配置。
注意:如果使用 java.net.useSystemProxies
属性启用了系统代理设置,则这些设置将覆盖 IDE 设置。
Mac OS 阻止用户运行 Java 该怎么办?
如果出现以下对话框:无法打开“java”,因为无法验证开发者,需按照以下步骤操作:
- 在弹出的对话框中点击 Cancel。
- 前往 Mac OS 系统设置,然后选择隐私与安全性。
- 在通用设置下,点击仍要打开按钮以启用 Java。
- 重新执行导致对话框弹出的 Jtest 操作。
- 对话框出现:macOS 无法验证“java”的开发者。您确定要打开它吗?时,点击打开。
另请参阅 https://support.apple.com/en-us/HT202491。
安装
如何防止我的机器码变化?
网络环境的变化可能会影响用于计算机器码的接口,从而导致机器码不稳定。您可以使用 PARASOFT_SUPPORT_NET_INTERFACES 环境变量指定一个稳定的接口,防止机器码变化。
- 设置 PARASOFT_SUPPORT_NET_INTERFACES 环境变量。
将变量值设置为稳定的以太网网络接口。请勿使用虚拟接口、临时接口或环回接口。
- Windows:将值设为网卡的 MAC 地址。您可以使用ipconfig-all
命令获取地址。 例如:SET PARASOFT_SUPPORT_NET_INTERFACES=00-10-D9-27-AC-85
- Linux:例如,将值设为“inet”或“inet6”系列中的一个网络接口。您可以使用
ifconfig
命令获取可用接口的列表。例如:export PARASOFT_SUPPORT_NET_INTERFACES=eth1
如果问题仍然存在,可以通过设置环境变量 PARASOFT_DEBUG_NET_INTERFACES 并将值设置为 true 来获取诊断信息。这将在标准输出中打印可与技术支持共享的检查步骤,以及用于计算您的机器码的界面。界面将标有 [SELECTED] 前缀。
如何将 jtestcli 和 JRE 从隔离中移除以允许它们在 Mac OS 中执行?
如果您是 Mac OS 用户,在执行 Jtest 时可能会遇到问题,因为 Jtest 不符合 Mac OS 常规的应用程序格式,并且在 App Store 之外下载。因此,jtestcli 和包含的 JRE 都将被系统隔离。
这是所有非 App Store 应用程序的常见问题。您可以在 Mac OS 隐私与安全性系统设置中手动允许打开每个可执行文件(请参阅 https://support.apple.com/en-us/HT202491)。要轻松移除这些文件的隔离属性,可运行 jtest_installation_folder/bin/remove_quarantine_flag.sh
脚本。
测试与分析
Jtest 更新到新版本后静态分析性能下降该怎么办?
新版本的 Jtest 可能需要更多内存来运行静态分析。您可以通过在 [INSTALL_DIR]/etc/jtestcli.jvm 配置文件中配置 -Xmx 选项来增加内存分配。
Jtest 在使用 Maven 构建项目时报告编译问题该怎么办?
如果 Jtest 报告在 Maven 测试范围中导入依赖项出现编译问题,可尝试使用 mvn test
命令运行 jtest:jtest
目标:
mvn test jtest:jtest
Java 解析器报告编译问题该怎么办?
默认情况下,Jtest 会将项目的编译输出路径添加到 Java 解析器所使用的 classpath 中。但在某些项目中,这可能会导致 Java 解析器报告编译错误。为解决该问题,可以尝试从 Java 解析器的 classpath 中排除编译器输出路径:
set jtest.parser.includeCompilerOutput=false
为什么运行 jtest:coverage
目标(Maven)或 jtest-coverage
任务(Gradle)会导致构建失败?
Jtest·coverage
目标/任务在 10.2.2 版本(插件版本 1.2.4)中已被移除,不再可用(请参阅从 10.x 迁移到 10.2.2 或更高版本)。执行此目标会导致构建失败,并显示以下消息:
[ERROR] Could not find goal 'coverage' in plugin com.parasoft.jtest:jtest-maven-plugin
. (Maven)
Task 'jtest-coverage' not found(Gradle)
Gradle 构建在配置为使用 Jtest 执行测试影响分析时失败该怎么办?
当您对多模块项目使用 Jtest 执行测试影响分析时,如果某个子模块中不包含被识别的受影响测试,Gradle 构建可能会失败。为防止 Gradle 构建未找到测试时失败,应配置以下选项:setFailOnNoMatchingTests(false)
Jtest 无法为 Gradle 运行的测试收集覆盖率信息该怎么办?
要启用覆盖率收集,Jtest 会自动为 Jtest·覆盖率代理配置 JVM 参数。覆盖这些参数会阻止 Jtest 收集覆盖率数据。如果 Gradle 构建脚本修改了 JVM 参数,应确保将它们添加(+=)到其他 JVM 参数中,以防止重写:
] |
] |
为什么使用 Maven 执行测试影响分析时会重新运行一个或多个未受到代码变更影响的测试?
- 当测试套件中至少有一个测试受到代码变更影响时,测试影响分析会重新运行整个测试套件。因此,如果测试套件包含未受影响的测试,它们也会重新运行。
- 在极少数情况下,测试影响分析可能无法识别包含或排除模式。 您可以手动过滤您的测试来尝试解决该问题;详细信息,请参阅手动过滤要重新运行的测试。
如何测试在文本流开头包含字节顺序标记(BOM)的源文件?
为确保正确处理和测试包含 BOM 的文件,您需要配置 Jtest 在解析文件时删除 BOM。将以下设置之一添加到 jtest.properties
配置文件中:
jtest.parser.bom=remove
- 删除 BOM,原始文件编码不变。jtest.parser.bom=recognize
- 删除 BOM 并使用 BOM 定义的编码覆盖原始编码
在使用 Maven 或 Gradle 运行测试时,Jtest 将不稳定测试报告为失败测试该怎么办?
默认情况下,Jtest 不区分在相同代码上运行时始终失败的测试和可能通过或失败的测试(不稳定测试)。 您可以通过启用已弃用的 XML 处理机制来让 Jtest 识别不稳定测试。 在 jtestcli.properties
配置文件中添加以下选项:
jtest.unittest.xml.results.processing.enabled=
true
请注意,启用已弃用的 XML 处理机制可能会影响测试执行速度。
使用 mockito-inline 运行 PowerMock 时测试失败该怎么办?
当在 classpath 中将 mockito-inline 放在 powermock 之前运行 PowerMock 测试时,可能会出现测试失败并显示以下异常:
NotAMockException: Argument should be a mock, but is: class java.lang.Class
这是由于 PowerMock 与 mockito-inline mock maker 的交互存在问题所导致的(详细信息,请参阅 PowerMock 问题)。
根据您的需求,有几种可行的解决方案:
- 删除 mockito-inline 或在 classpath 中将 powermock 放在 mockito-inline 之前。如果您不需要使用 Mockito 进行静态和构造函数模拟,则可以采用此方案。
- 更新 PowerMock 语句以使用支持 mockito-inline 的方法调用。一些 PowerMock 语句没有清晰的更新路径,需要其他解决方法。请参阅示例:
- 使用 mockito-inline 切换到 Mockito 静态和构造函数模拟。这需要重写所有 Powermock 调用以使用对应的 Mockito API。请参阅示例:
关于可以被模拟的类和方法存在一些限制。详细信息,请参阅 Mockito 静态和构造函数模拟限制。
更新 PowerMock 测试(静态模拟)- 示例
可以轻松修改以下导致问题的 PowerMock 调用:
- thenReturn()
- doReturn()
- doNothing()
例如:
PowerMockito.when(MyClass.staticCall(any())).thenReturn("value"); PowerMockito.when(MyClass.staticCall(any())).thenReturn("value1", "value2"); PowerMockito.doReturn("value").when(MyClass.class); MyClass.staticCall(any()); PowerMockito.doNothing().when(MyClass.class, "staticCall", any());
更新代码:
PowerMockito.when(MyClass.staticCall(any())).thenAnswer(invocation -> "value"); PowerMockito.when(MyClass.staticCall(any())).thenAnswer(invocation -> "value1").thenAnswer(invocation -> "value2"); PowerMockito.doAnswer(invocation -> "value").when(MyClass.class); MyClass.staticCall(any()); PowerMockito.doAnswer(invocation -> null).when(MyClass.class, "staticCall", any());
更新 PowerMock 测试(验证)- 示例
调用 verifyStatic() 或 verifyPrivate() 时,可能会遇到以下测试异常:
org.mockito.exceptions.misusing.NotAMockException: Argument passed to verify() is of type Class and is not a mock! Make sure you place the parenthesis correctly! See the examples of correct verifications: verify(mock).someMethod(); verify(mock, times(10)).someMethod(); verify(mock, atLeastOnce()).someMethod();
应该重构代码并手动验证所需的调用。
例如:
PowerMockito.when(MyClass.staticCall(any())).thenAnswer(invocation -> "value"); ... PowerMockito.verifyStatic(MyClass.class, times(1)); MyClass.staticCall(any());
更新代码:
int counter[] = new int[]{0}; PowerMockito.when(MyClass.staticCall(any())).thenAnswer(invocation -> { counter[0]++; return "value"; }); ... assertEquals(1, counter[0]);
对于 verifyPrivate(),唯一的解决方案就是手动验证所需的调用,因为 Mockito 不支持模拟私有方法。
例如:
PowerMockito.mockStatic(MyClass.class); PowerMockito.when(MyClass.class, "privateStatic", any()).thenAnswer(invocation -> inv.callRealMethod()); ... PowerMockito.verifyPrivate(MyClass.class, times(1)).invoke("privateStatic");
更新代码:
PowerMockito.mockStatic(MyClass.class); int counter[] = new int[]{0}; PowerMockito.when(MyClass.class, "privateStatic", any()).thenAnswer(invocation -> { counter[0]++; return inv.callRealMethod(); }); ... assertEquals(1, counter[0]);
将 PowerMock 测试转换为 Mockito(静态模拟)- 示例
PowerMock 代码:
PowerMockito.mockStatic(MyClass.class); PowerMockito.when(MyClass.staticCall(any())).thenReturn("value"); // test code PowerMockito.verifyStatic(MyClass.class, times(1)); MyClass.staticCall(any());
代码转换为 Mockito:
try (MockedStatic<FunctionsToMock> mocked = mockStatic(FunctionsToMock.class)) { mocked.when(() -> FunctionsToMock.staticCall(any())).thenReturn("value"); // test code mocked.verify(() -> FunctionsToMock.staticCall(any()), times(1)); }
将 PowerMock 测试转换为 Mockito(构造函数模拟)- 示例
PowerMock 代码:
FunctionsToMock mock = Mockito.mock(FunctionsToMock.class); PowerMockito.whenNew(FunctionsToMock.class).withAnyArguments().thenReturn(mock); when(mock.calculate()).thenReturn(1); // test code
代码转换为 Mockito:
try (MockedConstruction<FunctionsToMock> mocked = mockConstruction(FunctionsToMock.class, (mock, context) -> { when(mock.calculate()).thenReturn(1); })) { // test code }
Mockito 静态和构造函数模拟限制
Mockito 不支持以下用例:
- Mockito 不能模拟私有和原生方法。
- 以下类被排除在静态和构造函数模拟之外,以避免干扰 Mockito 内部实现:
- java.lang.Object
- java.lang.System
- java.lang.String
- java.lang.Thread
- “java.lang”包中的任何其他类,除了 UTA/模拟首选项的要包含的静态方法和构造函数表中明确列出的类
- java.util.Locale
- java.util.Optional
- java.util.Arrays
- java.util.Collections
- 集合和线程的 JDK 实现
- java.util.concurrent.atomic.AtomicBoolean
- java.util.concurrent.atomic.AtomicInteger
- java.util.concurrent.atomic.AtomicLong
- java.util.concurrent.atomic.LongAdder
- java.util.concurrent.atomic.LongAccumulator
- java.util.concurrent.atomic.DoubleAdder
- java.util.concurrent.atomic.DoubleAccumulator
- java.util.stream.StreamSupport
- java.io.File
- java.io.ByteArrayInputStream
- java.io.FileInputStream
- java.io.FileReader
Mockito 也不建议静态模拟 JDK 中的任何类。
- 模拟这些类将导致栈溢出异常或其他无限循环:
- java.io.File
如何诊断潜在的设置问题?
如果批量测试创建的效果不佳,这可能表明存在潜在的设置问题。
详细诊断问题的步骤:
- 禁用不添加无法提升覆盖率的测试。前往 Parasoft> 首选项> 单元测试助手,禁用只添加增加覆盖率的测试用例选项。
- 为目标测试类重新生成测试。
- 启用潜在设置问题建议。前往 Parasoft> 首选项> 单元测试助手> 建议,勾选潜在设置问题复选框。
- 通过 UTA 或 Jtest 运行测试。右键点击测试类,选择 More Run/Debug> Jtest <测试类名>
- 按照设置问题建议文档(潜在设置问题)的内容解读结果。
某个文件由于在源码控制系统和测试输入中的文件名不一致而无法测试该怎么办?
为正确处理和分析文件,Jtest 必须要能够将您在测试范围中提供的文件名(即项目中的文件名)与源码控制系统中的文件名进行匹配。因此,如果您使用的是区分大小写的源码控制系统,例如 Git,则需要确保文件名大小写一致。
报告
某些字符在 Jtest·报告中无法正确显示该怎么办?
Parasoft 产品生成的报告要求您的环境中使用无衬线字体。如果报告无法正确显示某些字符(如国家或地区的特殊字符),应确保系统上安装了无衬线字体。在 IDE 中工作
为什么当 UTA 文件的路径超过 250 个字符时测试执行会失败?
在 Windows 上,文件路径长度超过 250 个字符可能会导致该文件无法访问。如果您的工作空间嵌套在较深的文件夹层级中,某些 UTA 文件的路径可能会超过 250 个字符。无法访问测试执行所需的关键文件时,测试执行便会失败。
为确保 UTA 文件的路径不会超过限制,您可以考虑将工作空间文件夹移至文件夹层级目录中更高的层级。
Jtest 运行配置在 IntelliJ IDEA 中不生效该怎么办?
在极少数情况下,由于 IntelliJ 版本中的已知问题,Jtest 运行配置可能无法生效(详细信息,请参阅 https://youtrack.jetbrains.com/issue/IDEA-223124)。如果发生这种情况,您需要重启 IDE。Jtest 运行配置将在重启后生效。
无法在 Ubuntu Linux 中显示 HTML 内容(Jtest 规则文档、报告等)该怎么办?
使用最新的 Ubuntu Linux(21.10 或更新版本)并将基于 Snap 的 Firefox 浏览器作为默认浏览器时,Eclipse IDE 可能无法正确显示 HTML 内容(另请参阅:https://github.com/eclipse-platform/eclipse.platform.swt/issues/221)。有以下两种解决方法:
- 安装非 Snap 版本的 Firefox(或其他浏览器),并将其设置为系统默认浏览器。
- 在 Preferences > General > Web Browser > External web browsers 中将 Eclipse 配置为使用“外部 web 浏览器”。
注意:要将 Firefox 配置为“外部 web 浏览器”,应使用以下设置:
位置:/usr/bin/env
Parameters:firefox %URL%