Typically, an action may require a result to happen in the user interface before testing can continue. Since SWTBot can run much faster than a human can, waiting for a result of an action may be necessary. To demonstrate this, create a Java project with a single source file and then use the conditions to wait until the class file is compiled.
createJavaProject()
in the UITest
class.bot
to create a new Java project by copying the createProject()
method as a template.org.eclipse.core.resources
as a dependency to the plug-in.getProject()
, which returns an IProject
from ResourcesPlugin.getWorkspace().getRoot().getProject()
.getProject()
with the test project to get the src
folder .Test.java
from src
."class {}".getBytes()
bytes as a ByteArrayInputStream
.bot.waitUntil()
call to pass in a new anonymous subclass of DefaultCondition
.test()
method of the condition, return if the project's bin
folder has a file called Test.class
.getFailureMessage()
of the condition, return a suitable message.@Test public void createJavaProject() throws Exception { String projectName = "SWTBot Java Project"; bot.menu("File").menu("Project...").click(); SWTBotShell shell = bot.shell("New Project"); shell.activate(); bot.tree().expandNode("Java").select("Java Project"); bot.button("Next >").click(); bot.textWithLabel("Project name:").setText(projectName); bot.button("Finish").click(); final IProject project = getProject(projectName); assertTrue(project.exists()); final IFolder src = project.getFolder("src"); final IFolder bin = project.getFolder("bin"); if (!src.exists()) { src.create(true, true, null); } IFile test = src.getFile("Test.java"); test.create(new ByteArrayInputStream("class Test{}".getBytes()), true, null); bot.waitUntil(new DefaultCondition() { @Override public boolean test() throws Exception { return project.getFolder("bin").getFile("Test.class").exists(); } public String getFailureMessage() { return "File bin/Test.class was not created"; } }); assertTrue(bin.getFile("Test.class").exists()); }
waitUntil()
call and verify that the test fails.When the Test.java
file is created in the project, an event is fired that runs the Java compiler. This in turn results in the creation of both the bin
folder, as well as the Test.class
file that is being tested. However, both of these operations occur on different threads, and so while the test is running, if it needs to act on the generated file, it must wait until that file is created.
Although this example could have been implemented outside of SWTBot, it provides a simple way to block the execution until a particular condition occurs. This can be useful if the user interface is running some kind of long-running action and the code needs to wait until a certain dialog message is shown, or something that can be determined programmatically (such as the file's existence, as in this case).
Other types of conditionals and tests are possible as well; there is a waitWhile()
, which is similar to the bot's waitUntil()
but has the opposite behavior.
Note that when the wait condition is commented out, the test fails, because the test execution thread will hit the assertion before the Java compiler has been run.
One advantage of using the wait code in SWTBot is that if the condition doesn't occur within a given timeout then an exception is generated and the test will fail. Since the same wait condition is used elsewhere in SWTBot, the delay is configurable and can be changed externally.
Instead of using the source file as a text file, use SWTBot to open the New Class wizard by going to the File menu. Pass in the name of the project, the package, and the class; the source and class files should be created in the background. This is how integration tests (that show the application working from a user's perspective) can be implemented, instead of having a set of tests that show only the underlying libraries at work.
Q1. What is the name of the JUnit test runner that is required for SWTBot?
Q2. How are views shown with SWTBot?
Q3. How do you get the text value of a field in a dialog?
Q4. What is a Matcher
and when is it to be used?
Q5. How can values from the UI be returned to the user without having to worry about thread interaction?
Q6. When some asynchronous events are happening in the background, how can the test wait (without blocking the test) until a particular condition occurs?