Skip to content

Commit c0c5fdc

Browse files
IntelliJ plugin UI tests updates (#2264)
* UI tests updates * Separated supported and unsupported JDK. * Created test on unsupported JDK. * Maven added with IdeaMavenFrame. * WarningDialogFixture - for terminating running project on closure. * IntelliJ UI tests stabilized. * Created division function. * Added asserts for utbot tags. * Stability fixes for UI tests * Info notification xpath corrected to check UnitTestBot info notification only. * Wait for matching JDK appear in list if detecting in progress yet. * Readme.md updated with how to run UI tests --------- Co-authored-by: Alena Lisevich <alena.lisevych@gmail.com> Co-authored-by: Vassiliy.Kudryashov <Vassiliy.Kudryashov@gmail.com>
1 parent d1b7285 commit c0c5fdc

19 files changed

+344
-237
lines changed

utbot-intellij/readme.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
UT Bot Intellij Plugin
2-
======================
1+
UnitTestBot Intellij Plugin
2+
===========================
33

44
To run/debug plugin in IDEA:
55

@@ -10,4 +10,15 @@ To run/debug plugin in IDEA:
1010

1111
To compile plugin:
1212
* run `gradle buildPlugin`
13-
* find zipped plugin in build/distributions
13+
* find zipped plugin in build/distributions
14+
15+
## UnitTestBot Intellij Plugin UI Tests
16+
17+
* Comment `exclude("/org/utbot/**")` in utbot-intellij/build.gradle.kts
18+
* run IDEA in sandbox with IntelliJ Robot server plugin installed: `gradle runIdeForUiTests`
19+
* run **All** the tests in utbot-intellij/src/test/kotlin/org/utbot/tests
20+
21+
Note: projects are created first and only on new projects tests are executed.
22+
That is done for independency of each autotest run.
23+
24+

utbot-intellij/src/test/kotlin/org/utbot/data/IdeaBuildSystem.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.utbot.data
33
enum class IdeaBuildSystem (val system: String) {
44

55
INTELLIJ("IntelliJ"),
6-
GRADLE("Gradle")
6+
GRADLE("Gradle"),
7+
MAVEN("Maven")
78

89
}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package org.utbot.data
22

3-
enum class JDKVersion (val namePart: String, val number: Int) {
3+
enum class JDKVersion (val namePart: String, val number: Int, val supported: Boolean) {
44

5-
JDK_1_8(namePart = "-1.8", 8),
6-
JDK_11(namePart = "-11", 11);
7-
5+
JDK_1_8(namePart = "1.8", 8, true),
6+
JDK_11(namePart = "11", 11, true),
7+
JDK_17(namePart = "17", 17, true),
8+
JDK_19(namePart = "19", 19, false);
89
override fun toString() = namePart
910
}

utbot-intellij/src/test/kotlin/org/utbot/data/RunInfo.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package org.utbot.data
22

33
import java.time.LocalDateTime
44
import java.time.format.DateTimeFormatter
5+
import java.util.Random
56

67
val TEST_RUN_NUMBER = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
78
val DEFAULT_TEST_GENERATION_TIMEOUT = 60L
89
val NEW_PROJECT_NAME_START = "Aut_${TEST_RUN_NUMBER}_"
10+
val DEFAULT_PROJECT_DIRECTORY = "~\\IdeaProjects"
11+
var random: Random = Random()

utbot-intellij/src/test/kotlin/org/utbot/dialogs/DialogFixture.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ open class DialogFixture(
2828

2929
val title: String
3030
get() = callJs("component.getTitle();")
31+
32+
val closeButton
33+
get() = button(
34+
byXpath("//div[@class='DialogHeader']//div[@class='JButton']"))
35+
3136
}

utbot-intellij/src/test/kotlin/org/utbot/dialogs/NewProjectDialogFixture.kt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import com.intellij.remoterobot.fixtures.*
66
import com.intellij.remoterobot.search.locators.byXpath
77
import com.intellij.remoterobot.stepsProcessing.step
88
import com.intellij.remoterobot.utils.Keyboard
9-
import com.intellij.remoterobot.utils.waitFor
9+
import com.intellij.remoterobot.utils.keyboard
10+
import com.intellij.remoterobot.utils.waitForIgnoringError
11+
import org.utbot.data.DEFAULT_PROJECT_DIRECTORY
1012
import org.utbot.data.IdeaBuildSystem
1113
import org.utbot.data.JDKVersion
1214
import java.awt.event.KeyEvent
@@ -60,15 +62,12 @@ class NewProjectDialogFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteC
6062
fun selectJDK(jdkVersion: String) {
6163
step("Select JDK: $jdkVersion") {
6264
jdkComboBox.click()
63-
try {
64-
waitFor(ofSeconds(10)) {
65-
findAll<ComponentFixture>(byXpath("//*[@text.key='progress.title.detecting.sdks']")).isNotEmpty()
66-
}
67-
} catch (ignore: Throwable) {}
68-
waitFor(ofSeconds(20)) {
65+
var jdkMatching = jdkVersion
66+
waitForIgnoringError(ofSeconds(20)) {
6967
findAll<ComponentFixture>(byXpath("//*[@text.key='progress.title.detecting.sdks']")).isEmpty()
68+
jdkMatching = jdkList.collectItems().first { it.contains(jdkVersion) }
69+
jdkMatching.isEmpty().not()
7070
}
71-
val jdkMatching = jdkList.collectItems().first { it.contains(jdkVersion) }
7271
jdkList.clickItem(jdkMatching)
7372
}
7473
}
@@ -83,11 +82,15 @@ class NewProjectDialogFixture(remoteRobot: RemoteRobot, remoteComponent: RemoteC
8382
nameInput.doubleClick()
8483
keyboard.hotKey(KeyEvent.VK_CONTROL, KeyEvent.VK_A)
8584
keyboard.enterText(projectName)
85+
var input = DEFAULT_PROJECT_DIRECTORY
8686
if (location != "") {
87-
if (locationInput.hasText(location).not()) {
88-
locationInput.doubleClick()
89-
keyboard.hotKey(KeyEvent.VK_CONTROL, KeyEvent.VK_A)
90-
keyboard.enterText(location.replace("\\", "\\\\"))
87+
input = location
88+
}
89+
if (locationInput.hasText(input).not()) {
90+
locationInput.click()
91+
keyboard{
92+
hotKey(KeyEvent.VK_CONTROL, KeyEvent.VK_A)
93+
enterText(input.replace("\\", "\\\\"))
9194
}
9295
}
9396
this.findText(language).click()

utbot-intellij/src/test/kotlin/org/utbot/dialogs/UnitTestBotDialogFixture.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ class UnitTestBotDialogFixture(
1313
remoteComponent: RemoteComponent) : DialogFixture(remoteRobot, remoteComponent) {
1414
val keyboard: Keyboard = Keyboard(remoteRobot)
1515

16+
val sdkNotificationLabel
17+
get() = jLabel(
18+
byXpath("//div[@class='SdkNotificationPanel']//div[@defaulticon='fatalError.svg']"))
19+
20+
val setupSdkLink
21+
get() = actionLink(
22+
byXpath("//div[@class='SdkNotificationPanel']//div[@class='HyperlinkLabel']"))
23+
1624
val testSourcesRootComboBox
1725
get() = comboBox(
1826
byXpath("//div[@class='TestFolderComboWithBrowseButton']/div[1]"))
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.utbot.dialogs
2+
3+
import com.intellij.remoterobot.RemoteRobot
4+
import com.intellij.remoterobot.data.RemoteComponent
5+
import com.intellij.remoterobot.fixtures.*
6+
import com.intellij.remoterobot.search.locators.byXpath
7+
import com.intellij.remoterobot.utils.Keyboard
8+
9+
@FixtureName("MyDialog")
10+
@DefaultXpath("type", "//div[@class='DialogRootPane']")
11+
class WarningDialogFixture(
12+
remoteRobot: RemoteRobot,
13+
remoteComponent: RemoteComponent) : DialogFixture(remoteRobot, remoteComponent) {
14+
val keyboard: Keyboard = Keyboard(remoteRobot)
15+
16+
val terminateButton
17+
get() = button(
18+
byXpath("//div[@text.key='button.terminate']"))
19+
20+
val cancelButton
21+
get() = button(
22+
byXpath("//div[@text.key='button.cancel']"))
23+
24+
}

utbot-intellij/src/test/kotlin/org/utbot/pages/IdeaFrame.kt

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import com.intellij.remoterobot.search.locators.byXpath
77
import com.intellij.remoterobot.stepsProcessing.step
88
import com.intellij.remoterobot.utils.keyboard
99
import com.intellij.remoterobot.utils.waitFor
10+
import com.intellij.remoterobot.utils.waitForIgnoringError
1011
import org.assertj.swing.core.MouseButton
1112
import org.utbot.data.IdeaBuildSystem
1213
import org.utbot.dialogs.UnitTestBotDialogFixture
14+
import org.utbot.dialogs.WarningDialogFixture
1315
import org.utbot.elements.NotificationFixture
1416
import java.awt.event.KeyEvent
1517
import java.time.Duration
@@ -19,7 +21,6 @@ fun RemoteRobot.idea(function: IdeaFrame.() -> Unit) {
1921
find<IdeaFrame>(timeout = ofSeconds(5)).apply(function)
2022
}
2123

22-
@FixtureName("Idea frame")
2324
@DefaultXpath("IdeFrameImpl type", "//div[@class='IdeFrameImpl']")
2425
open class IdeaFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent) : CommonContainerFixture(remoteRobot, remoteComponent) {
2526

@@ -37,10 +38,6 @@ open class IdeaFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent)
3738
return@step remoteRobot.find(JMenuBarFixture::class.java, JMenuBarFixture.byType())
3839
}
3940

40-
val unitTestBotDialog
41-
get() = remoteRobot.find(UnitTestBotDialogFixture::class.java,
42-
ofSeconds(10))
43-
4441
val inlineProgressTextPanel
4542
get() = remoteRobot.find<ComponentFixture>(byXpath("//div[@class='InlineProgressPanel']//div[@class='TextPanel']"),
4643
ofSeconds(10))
@@ -61,8 +58,12 @@ open class IdeaFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent)
6158
get() = remoteRobot.find<NotificationFixture>(byXpath( "//div[@class='NotificationCenterPanel'][.//div[@accessiblename.key='error.new.notification.title']]"),
6259
ofSeconds(10))
6360

64-
val infoNotification
65-
get() = remoteRobot.find<NotificationFixture>(byXpath( "//div[@val_icon='balloonInformation.svg']/../div[@class='NotificationCenterPanel']"),
61+
val utbotNotification
62+
get() = remoteRobot.find<NotificationFixture>(byXpath( "//div[@class='NotificationCenterPanel'][div[contains(.,'UnitTestBot')]]"),
63+
ofSeconds(10))
64+
65+
val unitTestBotDialog
66+
get() = remoteRobot.find(UnitTestBotDialogFixture::class.java,
6667
ofSeconds(10))
6768

6869
@JvmOverloads
@@ -102,41 +103,63 @@ open class IdeaFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent)
102103
} else {
103104
menuBar.select("File", "Close Project")
104105
}
106+
try {
107+
remoteRobot.find(WarningDialogFixture::class.java, ofSeconds(1))
108+
.terminateButton.click()
109+
} catch (ignore: Throwable) {}
105110
}
106111

107-
fun callUnitTestBotActionOn(classname: String) {
112+
fun openUTBotDialogFromProjectViewForClass(classname: String) {
108113
step("Call UnitTestBot action") {
109114
waitFor(ofSeconds(200)) { !isDumbMode() }
110115
with(projectViewTree) {
111116
findText(classname).click(MouseButton.RIGHT_BUTTON)
112117
}
113118
remoteRobot.actionMenuItem("Generate Tests with UnitTestBot...").click()
114-
unitTestBotDialog.generateTestsButton.click()
115119
}
116120
}
117121

118122
open fun waitProjectIsOpened() {
119-
waitFor(ofSeconds(30)) {
123+
waitForIgnoringError(ofSeconds(30)) {
120124
projectViewTree.hasText(projectName)
121125
}
122126
}
123127

124128
open fun waitProjectIsCreated() {
129+
waitProjectIsOpened()
125130
}
126131

127132
open fun expandProjectTree(projectName: String) {
128133
with(projectViewTree) {
129134
if (hasText("src").not()) {
130135
findText(projectName).doubleClick()
131-
waitFor{
136+
waitForIgnoringError{
132137
hasText("src").and(hasText(".idea"))
133138
}
134139
}
135140
}
136141
}
137142

143+
open fun createNewPackage(packageName: String) {
144+
with(projectViewTree) {
145+
if (hasText("src").not()) {
146+
findText(projectName).doubleClick()
147+
waitFor { hasText("src") }
148+
}
149+
findText("src").click(MouseButton.RIGHT_BUTTON)
150+
}
151+
remoteRobot.actionMenu("New").click()
152+
remoteRobot.actionMenuItem("Package").click()
153+
keyboard {
154+
enterText(packageName)
155+
enter()
156+
}
157+
}
158+
138159
fun createNewJavaClass(newClassname: String = "Example",
139-
textToClickOn: String = "Main") {
160+
textToClickOn: String = "org.example") {
161+
waitProjectIsOpened()
162+
expandProjectTree(projectName)
140163
with(projectViewTree) {
141164
findText(textToClickOn).click(MouseButton.RIGHT_BUTTON)
142165
}

utbot-intellij/src/test/kotlin/org/utbot/pages/IdeaGradleFrame.kt

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package org.utbot.pages
33
import com.intellij.remoterobot.RemoteRobot
44
import com.intellij.remoterobot.data.RemoteComponent
55
import com.intellij.remoterobot.fixtures.DefaultXpath
6-
import com.intellij.remoterobot.utils.waitFor
6+
import com.intellij.remoterobot.utils.waitForIgnoringError
77
import org.utbot.data.IdeaBuildSystem
88
import java.time.Duration.ofSeconds
99

@@ -14,33 +14,31 @@ class IdeaGradleFrame(remoteRobot: RemoteRobot, remoteComponent: RemoteComponent
1414

1515
override fun waitProjectIsCreated() {
1616
super.waitProjectIsOpened()
17-
waitFor(ofSeconds(20)) {
18-
buildResult.retrieveData().textDataList.toString().contains("BUILD SUCCESSFUL")
17+
waitForIgnoringError (ofSeconds(60)) {
18+
statusTextPanel.hasText { it.text.contains("Gradle sync finished") }
1919
}
2020
}
2121

2222
override fun expandProjectTree(projectName: String) {
2323
with(projectViewTree) {
24-
try {
25-
waitFor(ofSeconds(10)) {
26-
hasText("src").and(hasText(".idea"))
27-
}
28-
} catch (ignore: Throwable) {} // if tree is collapsed - proceed to expand
24+
waitForIgnoringError(ofSeconds(10)) {
25+
hasText("src")
26+
}
2927
if (hasText("src").not()) {
3028
findText(projectName).doubleClick()
31-
waitFor{
32-
hasText("src").and(hasText(".idea"))
29+
waitForIgnoringError{
30+
hasText("src")
3331
}
3432
}
3533
if (hasText("main").not()) {
3634
findText("src").doubleClick()
37-
waitFor{
35+
waitForIgnoringError{
3836
hasText("src").and(hasText("main"))
3937
}
4038
}
4139
if (hasText("java").not()) {
4240
findText("main").doubleClick()
43-
waitFor{
41+
waitForIgnoringError{
4442
hasText("src").and(hasText("main")).and(hasText("java"))
4543
}
4644
}

0 commit comments

Comments
 (0)