2012-01-21 1 views
1

Можно создать дубликат:
Making FEST to wait for the application to loadСоздание Fest: ■ компонент поиска механизм ожидания для компонента существует

Примечание: Этот вопрос в основном идентичен this question. Поскольку ответов на этот вопрос не было, я решил расширить пример оттуда в исполняемый SSCE и предоставить дополнительную информацию, надеясь получить некоторую помощь.

Итак, вопрос в том, как вы должны обрабатывать поиск компонентов, когда искомый компонент еще не существует. Посмотрите на этот простой графический интерфейс с одной этикеткой.

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 должна быть поддержка для этого. Может быть, это не так? Невозможно дождаться компонентов?

ответ

1

Существует способ, вы можете написать условия для приостановки и ожидания. Ниже приведен пример вашего необходимого (noComponentFound и notReachedTimeout). Это можно сделать с помощью Pause.pause (новый компонент 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 под рамой было бы все гораздо проще:

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-> рамка) .table (согласовани) не принимает TypeMatcher, но просто GenericMatcher, поэтому мы все равно должны создать GenericMatcher.

ЕСЛИ вы не можете найти что-либо, theres всегда альтернативой фиксирования Pause.pause (5, TimeUnit.SECONDS);

Смежные вопросы