2017-10-10 29 views
1

SwingでJavaデスクトップアプリケーションを開発している間、単体テストを介して基礎となるコントローラ/モデルクラスだけでなく、UIを直接テストする必要がありました。始める方法:AssertJ Swingを使用したJava Swing GUIのテスト

このanswer (on "What is the best testing tool for Swing-based applications?")は、残念ながら廃止されたFESTを使用して提案されています。 しかし、FESTがどこに残っていたのか続くプロジェクトがいくつかあります。私が単体テストでこれまで使用していたように、特に(このanswerに記載されている)私の注意が引かれました:AssertJ

明らかにFESTに基づいており、Swing UIテストを書くのに使いやすい方法がいくつかあります。AssertJ Swingがあります。 しかし、初期/作業設定に入るのは、どこから始めるのが難しいので、扱いにくいです。私は2つのクラスだけからなる、次の例のUIのための最小限のテスト・セットアップを作成するにはどうすればよい


制約:Java SEの、SwingのUI、Mavenのプロジェクト、JUnitの

public class MainApp { 

    /** 
    * Run me, to use the app yourself. 
    * 
    * @param args ignored 
    */ 
    public static void main(String[] args) { 
     MainApp.showWindow().setSize(600, 600); 
    } 

    /** 
    * Internal standard method to initialize the view, returning the main JFrame (also to be used in automated tests). 
    * 
    * @return initialized JFrame instance 
    */ 
    public static MainWindow showWindow() { 
     MainWindow mainWindow = new MainWindow(); 
     mainWindow.setVisible(true); 
     return mainWindow; 
    } 
} 

public class MainWindow extends JFrame { 

    public MainWindow() { 
     super("MainWindow"); 
     this.setContentPane(this.createContentPane()); 
    } 

    private JPanel createContentPane() { 
     JTextArea centerArea = new JTextArea(); 
     centerArea.setName("Center-Area"); 
     centerArea.setEditable(false); 
     JButton northButton = this.createButton("North", centerArea); 
     JButton southButton = this.createButton("South", centerArea); 
     JPanel contentPane = new JPanel(new BorderLayout()); 
     contentPane.add(centerArea); 
     contentPane.add(northButton, BorderLayout.NORTH); 
     contentPane.add(southButton, BorderLayout.SOUTH); 
     return contentPane; 
    } 

    private JButton createButton(final String text, final JTextArea centerArea) { 
     JButton button = new JButton(text); 
     button.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent event) { 
       centerArea.setText(centerArea.getText() + text + ", "); 
      } 
     }); 
     return button; 
    } 
} 

私はので、私は答えを提供し、質問自体が非常に広いであることを承知しています私自身 - この特定の例を示しています。

+1

このQ&Aは、この回答に対するコメントのリクエストとして作成されました。https://stackoverflow.com/a/80222/5127499 – Carsten

答えて

1

TL;例プロジェクトはGitHubにあります。これはMavenプロジェクトであると仮定すると、


、あなたは少なくとも二つの依存関係を追加するまず必要があります:

  1. ユニットテストフレームワーク(例えばここjunitを - だけでなく、testngを使用することができます)
  2. 一致AssertJ Swingライブラリー(ここではassertj-swing-junitなど)

それはlが見ることができますIKEこの(あなたのpom.xml中:

/** 
* Base class for all my UI tests taking care of the basic setup. 
*/ 
public class AbstractUiTest extends AssertJSwingTestCaseTemplate { 

    /** 
    * The main entry point for any tests: the wrapped MainWindow. 
    */ 
    protected FrameFixture frame; 

    /** 
    * Installs a {@link FailOnThreadViolationRepaintManager} to catch violations of Swing threading rules. 
    */ 
    @BeforeClass 
    public static final void setUpOnce() { 
     // avoid UI test execution in a headless environment (e.g. when building in CI environment like Jenkins or TravisCI) 
     Assume.assumeFalse("Automated UI Test cannot be executed in headless environment", GraphicsEnvironment.isHeadless()); 
     FailOnThreadViolationRepaintManager.install(); 
    } 

    /** 
    * Sets up this test's fixture, starting from creation of a new <code>{@link Robot}</code>. 
    * 
    * @see #setUpRobot() 
    * @see #onSetUp() 
    */ 
    @Before 
    public final void setUp() { 
     // call provided AssertJSwingTestCaseTemplate.setUpRobot() 
     this.setUpRobot(); 
     // initialize the graphical user interface 
     MainWindow mainWindow = GuiActionRunner.execute(new GuiQuery<MainWindow>() { 

      @Override 
      protected MainWindow executeInEDT() throws Exception { 
       return MainApp.showWindow(); 
      } 
     }); 
     this.frame = new FrameFixture(this.robot(), mainWindow); 
     this.frame.show(); 
     this.frame.resizeTo(new Dimension(600, 600)); 
     onSetUp(); 
    } 

    /** 
    * Subclasses that need to set up their own test fixtures in this method. Called as <strong>last action</strong> during {@link #setUp()}. 
    */ 
    protected void onSetUp() { 
     // default: everything is already set up 
    } 

    /***************************************************************************************** 
    * Here you could insert further helper methods, e.g. frequently used component matchers * 
    *****************************************************************************************/ 

    /** 
    * Cleans up any resources used in this test. After calling <code>{@link #onTearDown()}</code>, this method cleans up resources used by this 
    * test's <code>{@link Robot}</code>. 
    * 
    * @see #cleanUp() 
    * @see #onTearDown() 
    */ 
    @After 
    public final void tearDown() { 
     try { 
      onTearDown(); 
      this.frame = null; 
     } finally { 
      cleanUp(); 
     } 
    } 

    /** 
    * Subclasses that need to clean up resources can do so in this method. Called as <strong>first action</strong> during {@link #tearDown()}. 
    */ 
    protected void onTearDown() { 
     // default: nothing more to tear down 
    } 
} 

実際のテストクラスは次のようになります。第二に

<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.12</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.assertj</groupId> 
    <artifactId>assertj-swing-junit</artifactId> 
    <version>1.2.0</version> 
    <scope>test</scope> 
</dependency> 

、私は通常、実際のテストからのテスト・セットアップのほとんどを分離するために、一つの基地テストクラスのために行きますその後、この:

public class MainWindowTest extends AbstractUiTest { 

    private JButtonFixture northButtonFixture; 
    private JButtonFixture southButtonFixture; 

    @Override 
    protected void onSetUp() { 
     this.northButtonFixture = this.frame.button(JButtonMatcher.withText("North")); 
     this.southButtonFixture = this.frame.button(JButtonMatcher.withText("South")); 
    } 

    @Test 
    public void testWithDifferingComponentMatchers() { 
     // use JTextComponentMatcher.any() as there is only one text input 
     this.frame.textBox(JTextComponentMatcher.any()).requireVisible().requireEnabled().requireNotEditable().requireEmpty(); 
     this.northButtonFixture.requireVisible().requireEnabled().click(); 
     // use value assigned in MainWindow class via JTextArea.setName("Center-Area") to identify component here 
     this.frame.textBox("Center-Area").requireText("North, "); 

     this.southButtonFixture.requireVisible().requireEnabled().click(); 
     // write our own matcher 
     JTextComponentFixture centerArea = this.frame.textBox(new GenericTypeMatcher(JTextArea.class, true) { 
      @Override 
      protected boolean isMatching(Component component) { 
       return true; 
      } 
     }); 
     centerArea.requireVisible().requireEnabled().requireText("North, South, "); 
    } 

    @Override 
    protected void onTearDown() { 
     this.northButtonFixture = null; 
     this.southButtonFixture = null; 
    } 
} 

プロジェクトで、このような基本的なセットアップを持っていたら、あなたはWかもしれませんさまざまな種類のコンポーネントマッチャーを調べて、潜在的にあなたの生活を少しでも簡単にするために、テストしたいコンポーネントのさまざまなものに対して電話番号setName()を呼び出してください。

+0

setUp()では、サードパーティのJava Webアプレットをどのように取得しますか?既に実行中? –

+0

@StevenVascellaroはAssertJ Swingサイトの説明を見ているかもしれません:http://joel-costigliola.github.io/assertj/assertj-swing-launch.html – Carsten

関連する問題