Test fixture to mimic a gradle project

Answered

Hi,

I'd like to discover the gradle version of a project in order to patch the gradle file with custom dependencies. However depending on the version of Gradle the dependency scope has to be be declared as `compile` for older gradle, or as `implementation` for later versions. I have identified the following APIs.

* org.jetbrains.plugins.gradle.util.GradleUtil#getGradleVersion(com.intellij.openapi.project.Project, java.lang.String)
* org.jetbrains.plugins.gradle.service.GradleInstallationManager#getGradleVersion(String)

I believe I need the first one. However I am not sure how to unit test the behaviour of this code. I have looked at some tests in the external system, from what I have seen the setup seems convoluted. But if I use something simple as that the gradle version is not what I expect.

public class GradleVersionTest extends LightJavaCodeInsightFixtureTestCase4 {
@Test
public void can_get_correct_gradle_version() {
PsiFile buildGradle = getFixture().configureByText("build.gradle", "");
getFixture().addFileToProject("gradle/wrapper/gradle-wrapper.properties", "distributionBase=GRADLE_USER_HOME\n" +
"distributionPath=wrapper/dists\n" +
"distributionUrl=https\\://services.gradle.org/distributions/gradle-7.2-bin.zip\n" +
"zipStoreBase=GRADLE_USER_HOME\n" +
"zipStorePath=wrapper/dists\n");

GradleVersion gradleVersion = GradleUtil.getGradleVersion(getFixture().getProject(), buildGradle);

Assert.assertEquals(GradleVersion.version("7.2"), gradleVersion);
}
}

This test fails as the the returned version is 6.8 instead of 7.2.

Also I would like to identify the DSL, Kotlin or Gradle, currently I am using the name of the file, is there other way that make use of the IntelliJ API ?

Thank you in advance.

0
5 comments

AFAIU it fails because you do not link/import the test project via External System API. see org.jetbrains.plugins.gradle.importing.GradleImportingTestCase

 

To distinguish Groovy/Kotlin, use com.android.tools.idea.gradle.dsl.api.GradleBuildModel and then switch depending on getPsiFile() instance.

0

Yes that is likely possible. But neither `GradleImportingTestCase`, `ExternalSystemImportingTestCase`, or `ExternalSystemTestCase` are available as they don't seem to be part of the `testFramework`. Which is why I tried something simpler using bits of the external system tests like

GradleProjectImportUtil.linkAndRefreshGradleProject(
getFixture().getProject().getBasePath(),
getFixture().getProject()
);

or 

ExternalSystemUtil.refreshProject(
getFixture().getProject().getBasePath(),
new ImportSpecBuilder(getFixture().getProject(), GradleConstants.SYSTEM_ID)
);

But I'm not yet successful yet. I'll try with a `HeavyPlatformTestCase`.

I'm not sure if it is relevant, but the build descriptor of my plugin declares this IJ plugin.

org.jetbrains.plugins.gradle.maven

 

0

Yes, please switch to heavy tests. These test classes are not published separately and/or are part of specific plugin and thus "local".

0

Ok I got this to work. Thank you !

 

 

1

Hi Yann Cebron

I have a question around testing. I'm not quite sure why in the heavy test the `PsiFile` modification don't get written to disk.

The test I have written extending `LightJavaCodeInsightFixtureTestCase` work as expected.

myFixture.configureByText("build.gradle", "");
GradleGroovyDependencies.appendDependencies(getProject()); // refactor to support kotlin DSL
myFixture.checkResult("dependencies {\n" +
" implementation('org.mockito:mockito-core:3.12.4')" +
"}");

However since I'm moving these to the `HeavyPlatformTestCase`, the setup and assertion is different. In particular the changes perfomed to the `PsiFile` reprensenting `build.gradle` are not persisted to disk (the PSI changes are performed within a `WriteCommandAction.writeCommandAction`). And I am asserting on the file on disk (eg via `Files.readString(buildGradle.toNioPath())`) in the fixture temporary project.

I have tried these API in the test code to persist the change to disk without success.

* `PsiDocumentManager.getInstance(getProject()).commitAllDocuments()`
* `PlatformTestUtil.saveProject(getProject())`

I do have a workaround in the new heavy test by using either the `Document` or the `PsiFile` `getText` method, which has the modification.

PsiManager.getInstance(getProject()).findFile(buildGradle).getText()

I think the tested code is OK, but I don't get what I'm missing in the test, maybe I missed something while analyzing `ExternalSystemTestCase`.

Thanks in advance.

0

Please sign in to leave a comment.