26. mai 2020
Analyser des ComponentNotFoundExceptions
In the above image, you can see a mouse click targeting a component (named mFile) in the application. Now whenever an action (like a mouse click) or a verification gets replayed QF-Test first needs to find the corresponding component in the application.
In case QF-Test is unable to identify the corresponding component in the application a ComponentNotFoundException get's thrown.
The following blog article delineates the different actions needed in order to analyse the root cause of such a ComponentNotFoundException.
Check that the component was present in the moment the action / verification got replayed
Although the above step may sound naive, users often miss to identify whether the target component is actually present in the application. In the moment QF-Test is replaying the action / the verification of course, not later on!
Whenever an exception occurs QF-Test (by default) logs a screenshot. Press the "Jump to run-log" button (see above error dialog) or press Ctrl+L (in case you already closed that dialog) in order to open the run-log. In the run-log press the "Find next error"-icon (see below screenshot) in order to jump to the exception. Now have a look at the screenshots in that run-log. Is the target component visible there? If yes, then continue by reading the next chapter "Check why QF-Test was unable to find the component although it is present in my application".
If the component is not visible, please check
- if the application needs more time till it displays the component
Here, it is likely that QF-Test was too impatient. QF-Test tried to find the target component although the application is not yet showing the component. Instead the application is for example showing a "I'm busy"-animation (like a progressbar).
Often users tend to work around this issue by specifing a waiting time in the 'Delay before' or the 'Delay after' attributes. However this is - most often - not recommended. In order to increase test execution speed, it is preferable to use a 'Wait for component', a 'Wait for document to load' or a 'Wait for component absence' node (with the latter it is possible to wait till the processbar disappears).
In order to insert a 'Wait for component': Copy/Paste the action / verification step that throwed the ComponentNotFoundException while replaying. (You now have this step two times). Then right click the FIRST step → Transform node into → Wait for component.
- if the action/verification is targeting a component that only appears sometimes
Here, the application is sometimes coming up with something that needs to get handled. This could for example be a dialog with a message like "Could not connect to server" that sporadically occurs after a given action.
Well, if you have an action targeting a component that sometimes appears (like a click on the OK-Button of such a dialog) and that sometimes does not appear (and that doesn't matter for the rest of the test) - you can use a try/catch construct (This construct tells QF-Test to ignore any exception for that particular step). The fastest way to get such a construct, is to right click the failing action node → Pack nodes → Try.
Alternatively, an 'If' node can be used in order to verify whether the target component is present before the action/verification node is getting executed.
- if the action/verification is targeting a component that only appears when certain conditions are met
For example the target component of your click/verification step is only available after the login step.
Although try/catch constructs as well as 'If' nodes (see above point "if the action/verification is targeting a component that only appears sometimes") often help here, too, it should be mentioned, that 'Dependency' nodes may be preferable here.
- if the component needs to get scrolled visible
Well, here scolling logic needs to get added. (Actually scrolling in QF-Test is an interesting topic for another blog article.)
- if this is a bug in your application
That means that the component is not available although it should be available. For example a component indicating an error message that should be there - but somehow that error message is not present.
Well this is something you need to discuss with your dev or bugfixing team ;)
- if the target component was removed by development team
This is also something that you need to discuss internally. Maybe the test-case should get removed or rewritten?
- if the target component is not shown because a previous action failed
This is rarely the case. But sometimes a previous action fails and QF-Test does not recognize that the previous action failed (e.g. a click that then opens a dialog with the desired component). Here the task is to analyze why the previous action failed.
Check why QF-Test was unable to find the component although it is present in my application
In order to avoid any misunderstandings, let me briefly discuss some fundamental ideas of the component recognition algorithm that is used by QF-Test.
The "QF-Test component ID" attribute of a an action/verification is not describing the target component by itself. Instead the string is referring to a node in the "Windows and Components" subtree of QF-Test. E.g. if we take the above mouse click:
Then this mouse click is referring to the mFile-node (right-click the node → Locate component):
It is the information in that referred "component definition node" that is used by the component recognition algorithm. In fact the string "mFile" is just a reference (Feel free to change the QF-Test ID of any component to make your tests more readable).
The reason why the recognition information is kept in one place is the following: It can be that this component in your application changes and then QF-Test may not be able to re-recognize that component anymore (e.g. the text of a button changes from OK to Continue). However you can have an arbitrary number of actions/verification nodes in your test-suite that target this component (e.g. 500 clicks on that button). Now instead of going through your test-suite and check where a mouse click is targeting that component, you only have to fix one node ...
As you may already know, QF-Test is using a probability algorithm for component recognition. And that algorithm determines each component in the component tree one after another. So in the image above, QF-Test will first search for the window, then for the MenuBar and then for the MenuItem named mFile.
Because QF-Test first searches for the window component etc. before it is trying to locate the target component, we need to find out which component QF-Test is not able to find. Is it the window itself (e.g. because the title of the window changed from "MyApplication - version 1.0" to "MyApplication - version 2.0")? Or is it any intermediate component?
If you have the possibility, simply re-record a click or check on the target component (And don't forget to delete the recording after analysis - otherwise your test-suite gets littered with recording / component definition nodes). Then by comparing the recorded versus the existing "Window and components" subtree, you can see where the tree differs - and thus which component definition node QF-Test was unable to find in your application.
For example let's re-record the click on the File-menu:
Here we can see that the window component is still the same (marked black) so QF-Test is still able to find / re-recongize the window component. Next is the MenuBar (marked red). And here we have two different component nodes ... This means, that QF-Test is unable to re-recognize the MenuBar component.
Another way is to have a look at the run-log. Whenever QF-Test is not able to find a component it is logging a message indicating the components present in the application and why QF-Test excluded which component:
After we have identified the component definition node that causes the problem check which node attribute changed. Then have a look at the following table:
- if the class attribute changed
The class attribute is indicating the component type QF-Test should look for. E.g. whether QF-Test should search for a Button, a List, a TextArea ...
It rarely happens, that the component class changes (e.g. that a button get's replaced by a label with the same functionality). If you nevertheless have that case, just change the class attribute accordingly.
- if the name attribute changed
The name attribute is the most dedicated attribute for component recognition. It should be a unique identifier of the given component in your application.
Developers can add such an identifier to each component in your application. However because these identifier are not visible to the user of your application, this is not often done. Furthermore these identifier are sometimes misused for other purposes - e.g. to store additional component related data.
If only one component is affected by a name attribute change, you can try whether clearing this attribute helps. Otherwise a NameResolvers may help in order to change whether and what QF-Test records as component name.
- if the feature attribute changed
The feature attribute gives the main feature QF-Test should use in order to recognize the component. This may for example be the the text of a component (e.g. Ok in case of an Ok-Button).
If you have any variable parts in the feature (e.g. the title of your window may either be "MyApplication version 1.0" or "MyApplication version 2.0" and so on), you can click the "As regex" checkbox and specify a regular expression, that then should match the feature.
Via an FeatureResolver it is possible to change what QF-Test takes/records as feature.
- if any extra feature attribute changed
Additional features which QF-Test may use in order to recognizes your component (similar to the feature attribute).
You can use an ExtraFeatureResolver to change (add/remove) extra features. Similar to a NameResolver / FeatureResolver an ExtraFeatureResolver can also affect which extra features QF-Test records (records at all / records by default).
- if any structure or geometry attribute changed
The structure / geometry is not often taken into account by QF-Test. In fact, this can only be an issue if QF-Test does not have a good name / feature or extra feature. Then QF-Test may recognize your component based on structure and/or geometry - e.g. if you have multiple OK-Buttons in your application and all buttons have the same name / feature / extra feature (or even no name / feature / extra feature).
So as long as you do have good name / feature or extra feature attributes ... ignore it (or correct / remove these geometry / structure attributes).
However when you do not have any good name / feature or extra feature attributes. Take the time to write some of the above mentioned resolver scripts for your component. This is often better then to rely on structure and geometry. (There are some problems with geometry based component recognition. E.g. replaying your tests on different machines often fails, as smaller / larger screens tend to change the geometry where a component gets rendered ...)
- Be sure to run your tests in an unlocked, active desktop. Otherwise you may get sporadic ComponentNotFoundExceptions everywhere (and if you rerun your test, other action/verification steps will/may be affected).