------------------------------------------------------------- README Notes written 2024 (AssertJ Swing GLI GUI testing groundwork laid in 2018-2019) ------------------------------------------------------------- Sections I Code Layout II Background Reading III Compiling and Running ------------------- CODE LAYOUT ------------------- - ext/testing/src/src/org/greenstone/gsdl3/testing/GSGUIUtil.java (Selenium, browser testing helper functions, needs revisiting in 2024) - ext/testing/src/src/org/greenstone/gsdl3/testing/GSGUITestingUtil.java (AssertJ Swing, GUI testing helper functions) - ext/testing/src/src/gstests/tutorials/RunGLITest.java (tests, rudimentary stage of testing the basic GUI helper functions above) ------------------- BACKGROUND READING ------------------- See the comments section at the top of ext/testing/src/src/gstests/tutorials/RunGLITest.java It lists the URLs and reading that I went through pertaining to junits, assertj swing and (if anything) on selenium to start off the automated gli testing work back in 2018. I can further gather the following from the current code. The following may be useful websites - interspersed throughout our code that uses assert swing, I find I'd added references to this website: https://joel-costigliola.github.io/assertj/assertj-swing-basics.html Good page for finding dialogs/windows, even if they may appear at some point in time: https://joel-costigliola.github.io/assertj/assertj-swing-lookup.html - https://junit.org/junit4/ (we appear to use junit4) - there's also the older wiki page by Sam that has his own work (not yet incorporated): https://wiki.greenstone.org/doku.php?id=internal:gs3_automated_testing ---------------------- COMPILING AND RUNNING ---------------------- 0. Have a fresh GS3, preferrably a code checkout from SVN so that you can tweak the code on any errors. Then set up the environment: source ./gs3-setup.sh 1. cd into GSDL3SRCHOME/ext and checkout the testing extension: svn co https://trac.greenstone.org/browser/gs3-extensions/testing/trunk/ testing 2. Run the default target in its src folder, which is build-tutorials-jar (which builds both the helper functions and the sequence of testing helper functions that get run) GS3/ext/testing/src>ant 3. Compile and run cycle: ant build-all-jars * ant run-tutorials-test (See point 5 first for EventDispatchThread/EDT exceptions encountered so far in GLI and fixes made) *build-all-jars calls ant targets: - build-util-jar: to compile up the testing helper function in GSGUITestingUtil.java (and in future hopefully also GSTestingUtil.java that will have helper functions using Selenium to test out web browser behaviour) - compile-tutorials-tests: to compile and jar up RunTestGLI.java, the sequence of steps that make up a test (like the sequnce of actions to complete the test of a GS3 tutorial). 4. To terminate the auto GLI gui testing: Ctrl+Shift+A You may further need to close the browser window and then may still need to press Ctrl-C in the terminal to return the prompt. NOTES: * When GLI runs automatically, it's very modal and there's no stopping it with random key presses. To stop GLI running, RunTestGLI.java documents we need to press Ctrl+Shift+A. Until the testing is done or an exception terminates the automated testing prematurely, testing won't otherwise stop. * There are occasions when Ctrl+Shift+A has no effect, on rare cases of unexpected popups that appear that are not part of the streamlined testing as set out and then the whole testing stops. On such an occasion, after 10 or 20 seconds the testing suite will stop by itself. 5. Running GLI immediately failed with Event Dispatch Thread exceptions (EDT exceptions). To get past this basic issue, a. - either in GathererProg.java I needed to move the instantiation of Gatherer into the SwingUtilities.invokeLater()'s run() at the bottom of GathererProg.main(), before gatherer.openGUI() - or I instantiate g_man in Gatherer inside a SwingUtilities.invokeLater() run() method b. In Gatherer.java, there were issues with the fileManager instantiation. So I put the contiguous lines instantiating assoc_man, f_man, c_man, recycle_bin into an invokeLater too. c. Then I can run "ant run-tutorials-test" and it jogs along OK automatically launching and interacting with GLI until it hits the snag I remember from long ago: the ProgressBar holding us up. These changes are documented in the svn diffs below. d. Many more such changes to GLI have now been made that I haven't here documented and would like to commit to svn with Dr Bainbridge's permission, after he looks them over (or a sample of them). More such changes may continue to be necessary as our testing expands to try more and more branches of GLI's code and EDT exceptions get triggered and get fixed. I'd prefer to commit all EDT related changes to GLI all in one go, at least on a "per tutorial" basis (per working test sequence of steps/actions that exercise a tutorial). Reminder: to shift code into the Event Dispatch Thread/EDT, there's SwingUtilities.invokeLater(), which is asynchronous. To be synchronous (code that Must happen now because the code that follows is dependent on results/successful finish of the sequence of events being shifted into the EDT), use SwingUtilities.invokeAndWait() in a try/catch. Pages that are useful - https://joel-costigliola.github.io/assertj/swing/api/org/assertj/swing/exception/EdtViolationException.html - VERY USEFUL BASICS: https://docs.oracle.com/javase/6/docs/api/javax/swing/package-summary.html#threading Index: src/org/greenstone/gatherer/Gatherer.java =================================================================== --- src/org/greenstone/gatherer/Gatherer.java (revision 38981) +++ src/org/greenstone/gatherer/Gatherer.java (working copy) @@ -723,14 +723,17 @@ // Now we set up an Authenticator Authenticator.setDefault(new GAuthenticator()); } - assoc_man = new FileAssociationManager(); - // Create File Manager - f_man = new FileManager(); - // Create Collection Manager - c_man = new CollectionManager(); - // Create Recycle Bin - recycle_bin = new RecycleBin(); - + SwingUtilities.invokeLater(new Runnable() { + public void run() { + assoc_man = new FileAssociationManager(); + // Create File Manager + f_man = new FileManager(); + // Create Collection Manager + c_man = new CollectionManager(); + // Create Recycle Bin + recycle_bin = new RecycleBin(); + } + }); if (GS3) { if (site_name==null) { site_name = Configuration.site_name; @@ -748,8 +751,11 @@ // Create GUI Manager (last) or else suffer the death of a thousand NPE's - g_man = new GUIManager(size); - + SwingUtilities.invokeLater(new Runnable() { + public void run() { + g_man = new GUIManager(size); + } + }); // Get a list of the core Greenstone classifiers and plugins Classifiers.loadClassifiersList(null); Plugins.loadPluginsList(null); Index: src/org/greenstone/gatherer/GathererProg.java =================================================================== --- src/org/greenstone/gatherer/GathererProg.java (revision 38981) +++ src/org/greenstone/gatherer/GathererProg.java (working copy) @@ -122,6 +122,8 @@ SwingUtilities.invokeLater(new Runnable() { public void run() { + //final Gatherer gatherer = new Gatherer(go); + // This line used to be done immediately after setGLIDirectoryPath() // and new Gatherer() above, but is now inside an invokeLater() to do graphical stuff here.