@Juan: your are a fast reader :) On Jun 9, 2:28 pm, Juan Pablo Gardella <[email protected]> wrote: > Thanks for share your experience!! > > 2011/6/9 Ed <[email protected]> > > > > > > > > > I like to share some testing experience with you, as I am very happy > > about it: > > > I have a GWT app that contains some complex business rules/logic which > > are difficult to test as they are embedded in the View. > > This is something that always frustrated me as bugs very difficult to > > track. > > > Used testing: > > 1) I use the MVP(C) pattern everywhere possible and make presenter > > tests. > > 2) I use a few GWT tests but they always give me problems as I am > > running in -noserver mode. > > 3) I use Selenium tests for display testing (running all Selenium > > tests take more then 30 hours on one machine). > > > I tried to extract/put this difficult-to-test embedded business logic > > (BL) in to a presenter, but things got very ugly and difficult to > > maintain. I found out that MVP is great but not always suitable. > > > ## An example of BL that I couldn't test with one of the above > > methods: > > I have a menu on the left side that show a display on the right side > > with text box entries that the user can fill in. The user can add and > > remove new entries and erase the content of a line that contains a > > collection of entries. > > The content of the entries are stored and retrieved from a central > > data model. It's retrieved when the display is shown and stored when > > the user selects another menu item such that it navigates away from > > the current display (not earlier as might want to undo his changes if > > they aren't valid for example). > > > ## I want to test the following scenario: > > Correct storage of the display value in the data model. That sounds > > simple but suppose a member erases some entries and removes some > > entries and creates a few new ones. You have to register the removed > > entries such that they are removed from the data model when the user > > selects another menu item (not earlier). > > Testing this with Selenium was hard as these details aren't easy made > > visible on the screen. Detail: i had to save the data model to the > > backend and restart the application such that the display is filled > > with the earlier stored data. > > However, it's important to test this as bugs are unacceptable in this > > part. > > > It was bothering me for quite some time now that I couldn't test this > > until GWT came out with the IsWidget interface in version 2.1. This > > interface is implemented by Widget. It's main use is for View's that > > implement IsWidget and can easier be mocked. But it's not really meant > > on detail level were I want to use it for. > > I was asking for a Widget interface for a long time and finally > > IsWidget appeared which was good enough for me... > > > ## My Solution to test the above: > > The idea: > > Let all widgets implement AsWidget instead of extending of Widget and > > create the Display widget as late as possible. > > With a few exceptions you could say: the actual creation of the > > display widget should only occur when it's attached to some panel. > > > Changes I made: > > In general I never use the GWT panel's directly, but use them trhough > > own Panel wrappers such that I can add functionality like insert/ > > removal animations (I opened a Feature request about this a long time > > ago: 3867) . > > I changes the add/insert/remove methods in the Panel wrapper to accept > > the IsWidget as type and store the IsWidgets widgets in a private > > collection. > > The contained GWT panel is only used when GWT.isClient yields true. > > Side note: because of this private collection, the panel wrapper > > returns the IsWidget instance that was added/inserted when requested > > with the method gwtWidget(int) instead as with the GWT panel, that > > always return the Widget instead, even if you inserted the IsWidget > > object that contains the Widget itself. This is confusing (see > > >http://groups.google.com/group/google-web-toolkit-contributors/browse... > > for discussion about this). > > > I changed the involved widgets to implement the IsWidget interface and > > no longer extend from Widget. > > The widget is only created when needed such that the method > > IsWidget.asWidget() is called. > > The idea is that you embed your view in your presenter (Embedded View > > Pattern), see Martin fowler for details about this. > > So basically we split up a widget in a Logical and Display widget. > > > That's basically it. It's pretty cool to finally be able to unit test > > (and fast) Widgets or a collection of Widgets, like a new world opens > > up :) > > Of course you this isn't some kind of Perfect solution, but perfect > > solutions don't exists in general, but you can test a lot more then > > before. > > > ## Fine tuning: > > I fine tuned things a bit: > > - A widget will also want to create it self when you set the style, > > debug id, etc... on the widget, so you have to fine tune your code > > such that it occurs only when the widget is created, or cache these > > settings and add them when the widget is created. I choose for the > > latter option through a small parent class called SimpleIsWidget that > > implements IsWidget that overrides methods like setStyleName, > > ensureDebugId, etc.. (add as much as you want). My widgets extends > > from SimpleIsWidget and the parent class will cache/buffer style/debug > > settings till it's created. It will automatically ask the subclass to > > create the display widget when needed or when the method asWidget() is > > called. This works pretty well. > > > - When listening for an event, the event will contain the display > > widget that triggered the event. However we often want the logical > > widget that created the display widget to perform additional actions > > as the display widget doesn't contain any BL. > > Example: class Entry that extends SimpleIsWidget, creates widget > > EntryDisplay that extends Widget that is contained in the received > > event (like a click event). > > I added the interface HasCreator that the created display widget can > > implement and will return the Logic widget. As such that the Logical > > and Display widgets are associated bidirectional. > > > I hope this helps you with your testing. > > > I also hope that the GWT dev team will further extend the usage of the > > IsWidget interface in the GWT framework such that testing becomes > > easier and more testing can be done without the use of the slow > > GWTTestCase method. I opened an issue about this some time ago and > > hope that developers recognize the need for this and vote the issue > > such that the GWT dev team will realize the required changes to gain > > better testing. > > The issue: 6113 (http://code.google.com/p/google-web-toolkit/issues/ > > detail?id=6113) > > > - Ed > > > -- > > You received this message because you are subscribed to the Google Groups > > "Google Web Toolkit" group. > > To post to this group, send email to [email protected]. > > To unsubscribe from this group, send email to > > [email protected]. > > For more options, visit this group at > >http://groups.google.com/group/google-web-toolkit?hl=en.
-- You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
