当前位置:   article > 正文

关于idea plugin测试那些事(纯手工翻译,只为打发时间,如果有错误,欢迎提建议,如果有意见,我相信别家一定更适合你)_codeinsightfixturetestcase

codeinsightfixturetestcase

让我们一起来愉快地测试自己开发的那些插件吧!

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

对于运行在IntelliJ平台中代码库上的大多数测试都是基于模块的功能性测试。这意味着:

– 因为这些组件大多数运行都需要基于真实的产品实现,并且这些测试并不能提供可视化界面(一些UI组件除外)。

– 测试的内容常常是需要验证一个完整的特性,而不是其中的一个功能。

– 并不直接测试Swing UI显示和执行,而是通过潜在模式进行变相测试。

– 大多数测试都需要获取一套源码文件或者一系列源码文件作为测试样本数据,基于此实现插件特性,然后将输出的结果与预想中的输出结果进行比较。输出结果可能是另外一套源码,也可能是在输入文件文本中做出一些标记,或者直接表现在测试代码中。

这种测试方法最大的优势在于这些测试是非常稳定的,并且一旦完成,无论底层的实现经历了多么丧心病狂的修改,对于测试代码也只需要极少量的维护和修改。

在一个超过十五年的开发时长,并且期间经历了很多次内部的重构的项目中,我们发现这种测试方法相比那些更加孤立的单元测试为我们带来的便利远远超过,这种测试方法在减缓测试执行效率增加在出现错误时调试的难度给我们带来的麻烦。

使用我们的框架时你还需要知道,我们的框架并不提供以下特性:

– 我们并不提供一种推荐的方法来模拟对象。虽然在我们的代码库中存在着一些测试使用了JMock框架,但是总的来说,我们发现模拟你的插件类中所需要的所有与IntelliJ平台的交互操作很困难,所以我们建议你直接在真实的组件中进行操作会比较好。

– 我们并不提供一个多方面的框架用于测试Swing UI组件。你可以尝试使用像 FEST或者Sikuli这样的工具进行插件的界面测试,虽然这么推荐,但是我们很皮地并不使用他们中的任何一个,甚至不提供关于他们使用方法的任何引导。取而代之,我们在测试Swing UI组件时往往使用手动测试。

测试和修复(维护)

IntelliJ平台测试方法并不和任何特定的测试框架绑定。事实上,IntelliJ IDEA 团队在测试项目的不同部分的时候还是会使用到例如,JUnit,TestNG和Cucumber这些测试框架来进行测试工作(死傲娇团队)。值得一提的是,大多数测试都是基于JUnit3的。

在写测试用例时,我们需要在使用一个已经为你设置好基本上所有的配置的标准的基类使用一个能给你手动设定测试配置且不与任何测试框架绑定的混合类之间做出选择。

通过前者,你可以通过 LightPlatformCodeInsightFixtureTestCase来执行测试。(尽管它在IntelliJ平台上是最长并且最丑的类名之一,它依然是我们推荐用来写测试用例的方式)

通过后者,你可以使用IdeaTestFixtureFactory来创建一个全新的开发环境,并且你必须调用相应的混和环境创建和初始化相关的方法

轻量级和重量级的测试

插件测试使用真实而并非模拟的IntelliJ平台环境,并且对于大多数的应用和项目组件,也会使用真实的实现。

为了测试插件在项目中的运行效果,而加载所有的项目组件常常是一件异常昂贵的操作,但是我们希望去避免针对每一次测试都去特地重新加载。根据加载和执行的时间,我们将IntelliJ平台的测试分为轻量级和重量级两种:

– 重量级测试在每一次测试的时候都会重新创建一个全新的项目

– 轻量级则会将尽可能地复用当前的项目

轻量级和重量级的测试使用不同的基类和混合类

注意:因为性能的差异,我们建议插件开发者尽可能编写轻量级的测试

编写一个轻量级的测试的常见方法是继承以下类:

LightPlatformCodeInsightFixtureTestCase 用以应对不需要任何依赖的测试情况。

LightCodeInsightFixtureTestCase 用以应对需要引入Java PSI文件结构或者其他任何相关的功能的测试情况。

当编写一个轻量级的测试用例时,你可以从项目中获取到你测试所需要的方方面面,比如模块类型,配置的SDK信息,界面,调用库等等。只需要继承LightProjectDescritor 类并且在LightCodeInsightFFixtureTestCase.getProjectDescriptor()方法中返回该对象即可。在执行每一次测试之前,如果这个测试对象返回同一个项目描述符(project descroptor)这个项目将会被复用,若发生了改变,则项目将会被重新创建。

注意:如果你需要测试一个针对多模块的项目组件,你必须编写一个重量级测试。

针对一个多模块Java项目的测试初始化代码一般如下:

final TestFixtureBuilder projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName());
// Repeat the following line for each module
final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());

测试项目和测试数据目录

测试夹具创建了一个测试项目环境。除非你自定义了项目创建过程,这个测试项目将会含有一个模块,且该模块中包含了一个被命名为src的源文件夹。源文件,可能存在于临时文件夹中或内存中,这取决于TempDirTestFixture采用的具体实现方式。

LightPlatformCodeInsightFixtureTestCase的实现基于内存。如果你通过调用IdeaTestFixtureFactory.createCodeInsightFixture初始化测试环境,你可以指定使用这种实现方式。

注意:如果你的测试环境基于内存,并且你中断了测试的执行,那么持久化的文件系统内存将会产生和内存结构的不同步问题,并且你可能会在你的测试过程中遇到出乎预料的错误信息。如果你在测试成功了很多次之后突然遇到了一个预料之外的错误信息,尝试再次运行这个测试,如果这并没有作用那,那么删除储存在你的沙箱文件夹的“system”子文件夹(通过Gradle设置中sandboxDirectory或者IntelliJ平台SDK的设置信息可以进行指定)

在插件中,我们常常会将我们的测试储存测试数据(比如插件作用的文件和插件执行后的输出文件)储存在testdata文件夹中。这仅仅是你插件中的一个文件夹,也并不在源码文件目录下。testdata文件夹下的文件常常并不是合法的源代码,也不会去编译。

我们必须重写LightPlatformCodeInsightFixtureTestCase.getTestDataPath()方法以指定testdata的储存位置。该方法默认设置为IntelliJ 平台资源树的一部分并且与第三方插件并不兼容。

注意:一种非常常见的一种插件测试模式是使用以被执行的测试方法的名称为基础的来搭建testdata文件路径。这种模式在使用不同的测试方法来测试同一个特性的不同方面时,能达成大部分代码的复用的目的。我们可以通过UsefulTestCase.getTestName()方法来获取测试方法的名称。

使用CodeInsightTestFixture中的copyFileToProject()方法和copyDirectoryToProject()方法,你可以复制testdata中的文件和文件夹到测试项目文件夹。

大多数插件测试中的操作都需要在向文件中写入或者修改数据(标注,完善或者其他操作)。基于内存的文本编辑器可以通过CodeInsightTestFixture.getEditor()方法获取。你可以使用CodeInsightTestFixture.configureByFile()方法或者configureByFiles()方法以达到从testdata文件夹中拷贝文件到项目文件夹中的目的。后者可以拷贝复数文件到项目文件夹中并且在文本编辑器中打开其中的第一个文件。

另外,你可以使用所有含有标记了 @TestDataFile注解参数的方法达到类似的目的。这些方法将特定的文件从testdata文件夹中拷贝文件到测试项目文件夹下,并且也会打开这些文件中的第一个文件,然后执行要求的操作比如标注,或者代码补全。

当一个文件在编辑器中被打开后,会使用特定的标注用以标记插入符号的位置后者选中的位置。你可以直接使用一下符号:

– 指定插入符号被插入的位置

– 指定了被选中的文本区域的开始位置和结束位置

– 指定被选中行的开始位置和结束位置

写测试

在大多数的情况下,一旦你已经把必要的文件拷贝到测试项目中并且将其加载到编辑器中,那么编写测试这件事情就变成了

1.将你的插件代码添加到测试中
2.添加对于相关测试框架的依赖

但是,对于很多常见的情况,使用框架提供的辅助方法能让测试更加简单:

– type()方法模拟了将字符和字符串键入到文本编辑器的过程

– performEditorAction() 模拟了一个action在编辑器环境中执行的过程

– complete() 模拟了代码补全的调用过程并且返回了补全列表中的所有显示元素的清单(如果补全并没有建议或者只有auto-insert的建议,那么返回null)

– findUsages() 模拟了Find Usages方法的调用并且返回了找到的具体使用信息

– findSingleIntention() 和 launchAction()配合使用,以模拟一个特定名称的intention action或者inspection quickfix的调用

– renameElementAtCaret()或rename()来模拟重命名操作

checkResultByFile()方法能将执行action的结果和预期的结果进行比较。包含预期结果的文件也能包含选中效果的标记文字(如)。如果你正在测试一个将会修改复数模块的插件(比如项目层面的重构),你可以使用PlatformTestUtil.assertDirectoriesEqual()来直接对两个项目进行比较。

对于标记的测试

写测试以测试各种各样的标记是很常见的一个任务。IntelliJ为此提供了一个检查功能和标记样式。

通过调用checkHighlighting()方法来测试当前编辑器加载的文件标记信息。这个方法的参数用于指定那种优先级的标记信息将会被拿来与预期结果进行比较:errors也就是报错信息始终会被纳入考核,而警告,弱警告,提示信息都是可选的。除此之外,我们可以通过使用testHighlighting()方法来将一个testdata中的文件加载到文本编辑器中并对其执行标记的操作。

如果你需要测试自定义的代码检查的操作(而不是通用的代码检查标记插件),你需要打开你正在测试的代码检查操作。在你的测试初始化方法或者直接在一个测试方法中调用CodeInsightTestFixture.enableInspections()(该方法必须在checkHighLighting之前进行调用才行)可以达到该目的。

标记的预期结果会直接显示在源文件中。平台支持一种可扩展的类XML标记语言来显示编辑结果。在最简单的情况下,标记符号看起来就像是这样:

<warning descr=“expected error message”>code to be highlighted</warning>

另外一种特定情况:

public int <warning descr=“The compareTo() method does not reference ‘foo’ which is referenced from equals(); inconsistency may result”>compareTo</warning>(Simple other) {
return 0;
}

标记名称表示需要表达的标记的优先级。
– <error>
– <warning>
– <weak_warning>
– <info>
– <inject> (for an injected fragment)
– <symbolName> (for a marker that highlights an identifier according to its type)

– 所有标记的优先级都可以直接通过名称来断定

标记tag还拥有以下可选属性用于描述tag:

– descr - expected message associated with the highlighter (if not specified, any text will match; if the message contains a quotation mark, it can be escaped by putting two backslash characters before it)
– foregroundColor, backgroundColor, effectColor expected colors for the highlighting
– effectType expected effect type for the highlighting (see EffectType enum for possible values)
– fontType expected font style for the highlighting (0 - normal, 1 - bold, 2 - italic, 3 - bold italic)

Nested tags are supported:

<warning>warning_highlight<info>warning_and_info_highlight</info>warning_highlight</warning>
Overlapping tags (annotations) are currently not supported in the test framework (but display correctly in the editor, albeit this is not an officially supported scenario):
<warning>warning_highlight<info>warning-and_info_highlight</warning>info_highlight</info>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/112138
推荐阅读
相关标签
  

闽ICP备14008679号