1

重複の可能性:
FEST がアプリケーションのロードを待機するようにする

注: この質問は基本的にこの質問と同じです。その質問に対する答えがなかったので、私はそこから例を実行可能な SSCE に拡張し、いくつかの追加情報を提供することにしました。

したがって、問題は、探しているコンポーネントがまだ存在しない可能性がある場合に、コンポーネントのルックアップをどのように処理すべきかということです。この単純な 1 つのラベルの GUI を見てください。

public class MyFrame extends JFrame {
    JLabel theLabel;

    public MyFrame() {
        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        theLabel = new JLabel();
        theLabel.setName("theLabelName");
        computeLabelContentOnWorkerThread();
    }

    private void computeLabelContentOnWorkerThread() {
        new SwingWorker<String, Void>() {
            @Override
            protected String doInBackground() throws Exception {
                Thread.sleep(5000);
                return "Info from slow database connection";
            }

            @Override
            protected void done() {
                try {
                    theLabel.setText(get());
                    add(theLabel);
                    pack();
                    setVisible(true);
                } catch (InterruptedException ignore) {
                } catch (ExecutionException ignore) {
                }
            }
        }.execute();
    }
}

そして、このテストケース:

public class TestOfDelayedComponent extends FestSwingJUnitTestCase {

    FrameFixture frameWrapper;

    @Before
    public void onSetUp() {
        MyFrame frame = GuiActionRunner.execute(new GuiQuery<MyFrame>() {
            protected MyFrame executeInEDT() {
                return new MyFrame();
            }
        });
        frameWrapper = new FrameFixture(robot(), frame);
        frameWrapper.show();
    }

    @Test
    public void testLabelContent() {
        String labelContent = frameWrapper.label("theLabelName").text();
        assertTrue(labelContent.equals("Info from slow database connection"));
    }
}

何が起こるのですか?ラベル コンポーネントの構築は、遅いワーカー スレッドに委譲されます。そのため、GUI が表示されたときにすぐにラベルが表示されるわけではありません。テスト ケースの実行時にラベルが表示されていないため、 でコンポーネント ルックアップを実行するframeWrapper.label("theLabelName")と、ComponentLookupException がスローされます。

問題は、この例外がスローされないようにするにはどうすればよいかということです。それが最上位のコンポーネントであるWindowFinder.findFrame("title").withTimeout(10000)場合、フレームが表示されるまでに遅延がある場合でも、フレームを見つけることができる FrameFinder オブジェクトを取得することができます。私が欲しいのはそれに似たものですが、JLabelなどの他のタイプのコンポーネント用です。


注: 確かに、この機能を自分で実装するのはそれほど難しくありません。行うのはかなり簡単です:

while(noComponentFound and notReachedTimeout){
    look for component using FEST
    sleep for a short delay
}

ただし、このようなループでテスト スクリプトをごちゃごちゃにする必要はありません。コンポーネントを待機することは、テスト スクリプトではあまり珍しいタスクではないように感じます。したがって、私の意見では、FEST でこれを行うためのサポートが必要です。多分これはそうではありませんか?コンポーネントを待つことはできませんか?

4

2 に答える 2

1

一時停止と待機の条件を記述する方法があります。必要な while(noComponentFound and notReachedTimeout) の例を次に示します。これは、Pause.pause(new ComponentFoundCondition(...),timeout_milis) で実行できます。例:

    frame = WindowFinder.findFrame("frame0").using(robot); 
   //Wait for the event of loading tables in the GUI before we fail looking for them concurrently
    final GenericTypeMatcher<JTable> matcher = new GenericTypeMatcher<JTable>(JTable.class) {
          @Override protected boolean isMatching(JTable table){ return (table instanceof myTable && table.getColumnCount()<20); }  //Condition has to be totally identitary for one particular component. If not, we will never reach condition and so a timeout will be thrown in next line
    };                                                                                                                                     

    Pause.pause(new ComponentFoundCondition("Waiting for myTable to load before I look for it...", frame.robot.finder(), matcher, frame.target), 50000); //frame.target argument can be omitted. We also put an associated 50 sec timeout even if the condition is never satisfied
    fixedTable = frame.table(matcher); //Look finally for the table now we are sure its loaded

さまざまなマッチャーでプレイできます。たとえば、フレームの下にテーブル myTable のタイプが 1 つだけある場合は、非常に単純になります。

    final ComponentMatcher matcher = new TypeMatcher(myTable.class); // We could use an easier TypeMatcher, because we would not need to add any additional distinction apart from the class type 
    Pause.pause(new Condition("Waiting for myTable to load...") { // If we are totally sure that there will be only one occurrence, we can use here the simplest form like above new ComponentFoundCondition("DebugMsg", frame.robot.finder(), matcher, frame.target)
        @Override public boolean test() { return !frame.robot.finder().findAll(frame.target, matcher).size().isEmpty(); } // If not we need a custom condition that checks for >0 instead of =1 results like ComponentNotFound.
     }, 50000); 

問題は、 (component->frame).table(matcher) が TypeMatcher を受け入れず、GenericMatcher のみを受け入れることです。そのため、とにかく GenericMatcher を作成する必要があります。

何も見つからない場合は、Pause.pause(5, TimeUnit.SECONDS); を静的に修正するという代替手段が常にあります。

于 2012-07-31T10:54:23.007 に答える
0

私は Fest を使用していませんが、Pause.pause はこのページで興味深いようです: http://www.pushing-pixels.org/2009/09/23/using-fest-swing-to-test-flamingo-components.html

于 2012-01-31T01:59:04.800 に答える