Creating a FEST component search engine: s waits for a component to appear

Possible duplicate:
Creating FEST to wait for application loading

NOTE. This question is basically identical to this question . Since there were no answers to this question, I decided to extend the example from there into the executable SSCE and provide additional information, hoping to get some help.

So the question is how should you handle component searches when the component you are looking for does not exist yet. Take a look at this simple shortcut 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(); } } 

And this test case:

 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")); } } 

What's happening? The design of the label component is delegated to the slow worker thread. Thus, the shortcut will not appear immediately after the appearance of the GUI. When the test case was started, the label did not appear, therefore, when performing a component search in frameWrapper.label("theLabelName") , a ComponentLookupException exception is thrown.

Question: how can I eliminate this exception? If it was a top-level component, I could do WindowFinder.findFrame("title").withTimeout(10000) to get the FrameFinder object that it finds, can find the frames, even if it's a delay before they appear. What I want looks like this, but for other types of components, such as, for example, JLabel.


NOTE. Of course, not all will be difficult to implement this functionality. That would be pretty simple:

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

However, it would be nice if you were not forced to clutter up test scripts with such cycles. It seems that waiting for components is not too unusual a task in test cases. Therefore, in my opinion, in FEST there should be support for this. Maybe this is not so? Is it impossible to wait for the components?

+1
source share
2 answers

There is a way to write Conditions for suspension and waiting. Below is an example of your required (noComponentFound and notReachedTimeout). This can be done using Pause.pause (new component ComponentFoundCondition (...), timeout_milis). Example:

  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 

You can play with different helpers. For example, if there was only one type of myTable table under the frame, it would be very simple:

  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); 

The problem is also that (component-> frame) .table (matcher) does not accept TypeMatcher, but just GenericMatcher, so we need to create a GenericMatcher after all the rest

IF you cannot find anything, theres always an alternative to fixing estatically Pause.pause (5, TimeUnit.SECONDS);

+1
source

I don't use Fest, but Pause.pause looks interesting on this page: http://www.pushing-pixels.org/2009/09/23/using-fest-swing-to-test-flamingo-components.html

0
source

Source: https://habr.com/ru/post/1390228/


All Articles