There are a lot of things that you can automate in Alma; either with the jobs menu or your own programming with the Alma API's. But what happens when there is a task that you want automated, but you can't access it through the jobs menu or Alma API? What then?
That's exactly what we encountered at UNILINC when we needed to automate a repetitive task.
The Distribute Resource Sharing Network Configuration is a task that we run twice a day. It distributes the changes to the Resource Sharing Partners from the NZ (Network Zone) to the IZ (Institution Zone).
Another constraint we faced was that we needed to get the changes to the IZ completed before the start of business because the changes to the Resource Partners related to activation or deactivation of a library on that day. Naturally the only way that a library would have an up to date list is if we updated it before the library opened for business. So how did we do it?
In a nutshell we solved the dilemma by using automated testing tools to perform the steps that we would have done manually. This article will discuss the steps we took.
For testing purposes we used a desktop PC for development with:
- WAMP - software that allows your computer to run as a local web-server. You can download this software from http://www.wampserver.com/en/
- Codeception - a PHP code library for automated testing. You can download this software from http://codeception.com/ but in this tutorial we'll install it using the preferred method of composer (see below).
- Composer - a dependency manager for PHP. This is used to install Codeception. You can get composer from https://getcomposer.org/download/
- Selenium - Browser automation. You can download this software from http://docs.seleniumhq.org/download/
- PhantomJS - Browser automation, but without the need for a browser. Perfect for running on a server. Download PhantomJS from http://phantomjs.org/download.html
This article isn't going to show you how to install everything; there are plenty of instructions and documentation on their respective websites for that. Heck, most of the stuff is a single click executable so it shouldn't be terribly difficult to get started. So go ahead and get WAMP and Composer installed, and download Selenium and PhantomJS.
Check that Composer is running
On a command prompt type the following command
You should get some output that tells you the version and the build date etc. If you've installed composer properly then you should get something similar to what is shown in the screen shot.
If you get the message
'composer' is not recognized as an internal or external command, operable program or batch file
then you'll need to look at updating your path variables in Control Panel | System | Advanced System Settings | Environment Variables and add the directory where composer is installed to the Path Variable. Make sure you reload the command prompt window to ensure that the path changes take effect.
Create a new working directory and from the command prompt type the following command.
composer require "codeception/codeception"
This will install codeception as a sub-folder in our working directory. There is quite a lot to install, but composer will handle the dependencies and the sub-projects for us.
It won't take too long to install and you should find two new files created plus a vendor directory. The files that were created store information about the packages we've installed, their versions and make it easy for us to upgrade later on if necessary.
The vendor directory contains the programming files for all the packages we've downloaded, i.e. Codeception.
Setting up Codeception
Nothing bets reading the documentation, and the quick start (http://codeception.com/quickstart) guide is very similar to what we're going to be doing here. Run the following command
This sets up our initial testing framework, and creates a new folder called tests. Inside that folder we have unit, functional and acceptance testing folders. We can use these or we can create our own test suite.
Create a Test Suite
We're going to create a Selenium test suite. To do that we run this command:
codecept generate:suite Selenium Selenium
Executing the command creates a new 'Selenium' folder and selenium.suite.yml file in the tests folder.
Now we need to modify the selenium.suite.yml file. Change the file from this
class_name: SeleniumTester modules: enabled: - \Helper\Selenium
To this (making sure there are no tabs used otherwise your configuration file will be corrupted)
class_name: SeleniumTester modules: enabled: - \Helper\Selenium - WebDriver: url: 'https://ap01-a.alma.exlibrisgroup.com' browser: firefox
What we've done here is to set up our test suite to use the Firefox browser for testing (with Selenium). This won't work on a server, but it will on a PC. The reason why we approach the development this way is because it can be easier to see the progress of your test visually with a web-browser rather than trying to figure out the meaning of the command line output (especially if you're very new to this).
Needless to say, once we have our automation (test) working properly, then we'll start using PhantomJS (i.e. a browser without the graphical interface that can be used on a server).
Whenever we make a change to the modules section in a .yml file we need to 're-build' codeception. We do that with this command.
This simply makes any new functions available to our test suite based on the modules that have been included. I.e. the web-driver functions http://codeception.com/docs/modules/WebDriver.
Build our first 'welcome' test
We're now ready to build our first test. Type in the following command to create a 'welcome' test in the selenium test suite.
codecept generate:cept selenium welcome
In the tests/selenium directory, a new file has been created called welcomeCept.php
We can open this file and see that a start has been made.
<?php $I = new SeleniumTester($scenario); $I->wantTo('perform actions and see result');
If we have a look at the docs for web-driver (http://codeception.com/docs/modules/WebDriver) we can see all the actions that we can perform. Let's start off by adding something simple.
amOnPage - this is the webpage that we should start off on. The start of the url was completed earlier in the selenium.suite.yml file.
see - I am expecting to see this text on the webpage. The text itself is within an anchor tag, so we could fine tune the last code statement by specifying that the text we're expecting to see should be inside an <a> tag.
Running the 'welcome' test
Before we can run our welcome test we need to have the Selenium server running first. Open up a new command prompt to where Selenium has been downloaded. You should be able to run the server by running the command below (adjusting for the filename)
java -jar selenium-server-standalone-2.xx.xx.jar
If everything is running properly you should get output similar to what is shown in the screen shot below.
And then when we run the test
codecept run selenium
We should see a result similar to what is shown below.
If we change our code to look for something that is not on the webpage, then we'll get an error. The output even shows us what steps were completed, and where the error occurred.
If we look into the Codeception web-driver documentation we will find a few actions that will help us deal with login forms.
We can couple that with the developer tools that come with Chrome to investigate what our field names are.
They are username and password respectively. The login button is aptly named Login.
Now we can modify our welcome test, making sure to substitute the placeholders for username and password for something that will actually work.
<?php $I = new SeleniumTester($scenario); $I->wantTo('perform actions and see result'); $I->amOnPage('/mng/login?institute=blah&auth=local'); $I->see('http://status.exlibrisgroup.com/'); $I->fillField('username', 'my-username-for-alma'); $I->fillField('password', 'my-password-for-alma'); $I->click('Login');
If we now run this test, nothing changes with the output on the command line - but this is to be expected because we haven't added any additional tests. What we do see however is the login form being displayed in the Firefox browser, login credentials being filled in, the login button being clicked and we are then redirected to the main Alma page.
Unfortunately after we login, there are no further instructions, so Codeception then closes down the browser and we are left with all but a glimpse of the main page.
Let's fix that by waiting a few seconds before the browser closes. We can do that by adding the following line:
$I->wait(4); //wait 4 seconds.
Once we’ve logged into Alma, we can bring up the main menu by pressing the F2 key. The question is can we do the same in Codeception? Can we press the F2 key?
The answer is yes we can. If we’ve had a good look at the web-driver documentation then we would have found the pressKey action.
If we take our search a little further, we would find the WebDriverKeys documentation as well (and that the F2 key is available for us too).
So, we’ll add the F2 keypress to bring up the menu, but let’s also add a test as well. I’m going to find a sub-heading on the main menu. I’ll go with ‘advanced tools’ that comes under the Administration column. You may not have this sub-menu, so go ahead and use another one and modify the code accordingly.
<?php $I = new SeleniumTester($scenario); $I->wantTo('perform actions and see result'); $I->amOnPage('/mng/login?institute=blah&auth=local'); $I->see('http://status.exlibrisgroup.com/'); $I->fillField('username', 'my-username-for-alma'); $I->fillField('password', 'my-password-for-alma'); $I->click('Login'); $I->wait(4); $I->pressKey('#body_id_xml_file_', WebDriverKeys::F2); $I->see('Advanced Tools'); $I->wait(2);
Now we have 1 test and 2 assertions (each separate file is a test). Also when we see these actions being performed in the web-browser there is a slight delay from when the test ends to when the browser is eventually shut down.
Clicking the menu item (xPath)
Using the same steps as before (using the developer tools), we’ll find the id of the link that we want to click, and incorporate that for our click action.
$I->expectTo('Click Distribute Resource Sharing Network Configuration'); $I->click("//li[@id='MENU_LINK_ID_com.exlibris.dps.adm.general.menu.initial.Fulfillment.FulfillmentHeader.distribute_resource_sharing_network_configuration']/a"); $I->wait(3);
The click parameter is using xPath, which is a way to navigate an XML document. Discussing XPath is outside the scope of this article, however you can find documentation and an explanation for the syntax used here:
When we add this sample of code to our test, we progress to the next stage where a dialog box is displayed and we’re asked to confirm our choice.
Clicking the confirmation button
Using the Developer tools in Chrome like we did before, we can find the id of the buttons.
We can now use this with the techniques we learnt about XPath to click the appropriate button. In fact it might be a good idea to add another assertion. We’ll check to see if the text ‘Confirm’ is indeed present, and once again we’ll also wait a bit before the browser closes down.
$I->see("Confirm"); $I->expectTo('Click Confirm'); //$I->click("//input[@id='PAGE_BUTTONS_cbuttonconfirmationcancel_confirmation']"); $I->click("//input[@id='PAGE_BUTTONS_cbuttonconfirmationconfirm']"); $I->wait(2);
Now with the extra assertion we can see that in the output. We have 1 test and 3 assertions.
Checking the Jobs History
Of course it would be useful to check Alma and see if the job actually did run. When I look at the browser doing stuff on its own, it certainly looks like it is doing something. But is it really doing something? Well, when I look at the Jobs History it certainly appears to have done exactly what we’ve asked.
So far we've managed to use Codeception to automate one of our tasks that we couldn't access thru the jobs menu or API. This used the Firefox browser, and we could see every step that it took. The big question is, can we replicate these steps on a server that can’t run a desktop application like Firefox?
The answer is PhantomJS.
In our earlier section 'Running the welcome test', I had instructions on how to run the selenium server.
java -jar selenium-server-standalone-2.xx.xx.jar
We can now stop that application, and run PhantomJS instead.
If PhantomJS has been set up properly, we should see something like this when we run it.
And we don’t have to make any changes to our code or configuration settings. Just run the codecept test suite with PhantomJS running instead of Selenium. You’ll also notice that not having to open up a browser to perform the tasks means that our tests run quicker, and that is with 11 seconds worth of waiting at various stages as well.
Codeception is a wonderful testing framework. It brings a variety of underlying technologies together and allows the developer to use each one with the same style and syntax. However, we didn’t use Codeception for testing. We used it to automate a repetitive task, and over the last 4 months it has worked flawlessly.
The other important aspect of this development is that now that the setup has been done, replicating other tasks to be automated is a matter of following the same process. The syntax is easy and descriptive, and from development to production, we can see how we’re progressing each step of the way. More importantly, the code we write doesn’t need to change from development to production, from seeing a web browser opening up and performing the steps to using PhantomJS. But more importantly, a repetitive task that needed to be done every day, early in the morning, has now been fully automated.
Application Development and Systems Support