SWTBot测试Eclipse RCP:原生对话框输入及SWTKeyboard反斜杠方案
问题
使用SWTBot对Eclipse-RCP应用做UI测试时,需要打开原生文件对话框完成文件上传,但SWTBot无法直接操作这类原生对话框。尝试用SWTKeyboard在对话框地址栏输入绝对路径规避鼠标操作,却发现keyboard.typeText()无法输入路径中的:和\:已通过快捷键解决:的输入,但德语键盘下输入\需要ALT_GR+ß,而ß不是SWTKeyboard支持的有效按键,暂时没有解决办法。
临时实现代码如下:
public void setSourceFile(String absoluteFilePath) { if (swtBot.comboBoxWithLabel("Source:").selectionIndex() == 0) { // 打开文件对话框 swtBot.button(" ... ").click(); Keyboard keyboard = KeyboardFactory.getSWTKeyboard(); // 向地址栏插入路径 for (char c : absoluteFilePath.toCharArray()) { switch (c) { case ':': keyboard.pressShortcut(SWT.SHIFT, '.'); break; default: keyboard.typeCharacter(c); break; } } keyboard.pressShortcut(Keystrokes.CR); } }
求问:是否有更优的原生对话框输入方案?或者如何用SWTKeyboard输入反斜杠?
解决方案
1. 解决德语键盘下反斜杠的输入问题
德语键盘中\的输入组合是ALT_GR+ß,在SWT中ALT_GR对应SWT.MOD2(部分环境下等价于SWT.CTRL | SWT.ALT),而ß可直接作为字符传入pressShortcut方法。修改字符处理逻辑,添加对\的处理:
case '\\': // 模拟ALT_GR + ß keyboard.pressShortcut(SWT.MOD2, 'ß'); break;
如果SWT.MOD2在你的环境中不生效,可尝试用SWT.CTRL | SWT.ALT替代:
case '\\': keyboard.pressShortcut(SWT.CTRL | SWT.ALT, 'ß'); break;
2. 更优的原生对话框处理方案
方案一:绕过原生对话框,直接调用应用逻辑
如果你的Eclipse-RCP应用代码具备可测试性,可以直接调用处理文件上传的内部方法,跳过原生对话框的交互。比如找到负责加载文件的服务类或方法,直接传入文件路径,完全规避UI层面的原生对话框操作。
方案二:使用Java AWT Robot模拟输入
如果SWTKeyboard的局限性无法解决,可使用Java自带的java.awt.Robot类模拟键盘输入,它对原生控件的兼容性更好:
import java.awt.Robot; import java.awt.event.KeyEvent; public void setSourceFile(String absoluteFilePath) { if (swtBot.comboBoxWithLabel("Source:").selectionIndex() == 0) { swtBot.button(" ... ").click(); try { Robot robot = new Robot(); // 等待对话框加载完成 robot.delay(500); // 逐个字符输入路径 for (char c : absoluteFilePath.toCharArray()) { switch (c) { case ':': robot.keyPress(KeyEvent.VK_SHIFT); robot.keyPress(KeyEvent.VK_PERIOD); robot.keyRelease(KeyEvent.VK_PERIOD); robot.keyRelease(KeyEvent.VK_SHIFT); break; case '\\': // 德语键盘:ALT_GR对应Ctrl+Alt,ß对应Z键位置(需根据实际键盘调整) robot.keyPress(KeyEvent.VK_CONTROL); robot.keyPress(KeyEvent.VK_ALT); robot.keyPress(KeyEvent.VK_Z); robot.keyRelease(KeyEvent.VK_Z); robot.keyRelease(KeyEvent.VK_ALT); robot.keyRelease(KeyEvent.VK_CONTROL); break; default: // 处理普通字符,区分大小写 int keyCode = KeyEvent.getExtendedKeyCodeForChar(c); if (Character.isUpperCase(c)) { robot.keyPress(KeyEvent.VK_SHIFT); robot.keyPress(keyCode); robot.keyRelease(keyCode); robot.keyRelease(KeyEvent.VK_SHIFT); } else { robot.keyPress(keyCode); robot.keyRelease(keyCode); } break; } robot.delay(50); } // 按下回车确认选择 robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); } catch (Exception e) { e.printStackTrace(); } } }
注意:
Robot类的键码需根据实际键盘布局调整,比如德语键盘中ß对应的键码可能是VK_Z,需自行验证。
方案三:强制SWT使用非原生对话框
部分SWT应用可通过设置系统属性,强制使用SWT自带的非原生文件对话框,这样就能被SWTBot直接操作:
// 在测试启动前设置该属性 System.setProperty("swt.useDefaultFileDialog", "false");
如果你的应用支持这个属性,设置后文件对话框会变成SWT实现的非原生版本,就可以用SWTBot的bot.fileDialog()方法直接操作,无需模拟键盘输入。
内容的提问来源于stack exchange,提问作者K0rWin

