Developing and Testing an 
open source web application 
ELUNA 2014 Montreal 
Michael Cummings, GWU
Agenda ELUNA 2014 
Agenda 
Developing a customized library 
catalog using API’s 
User Interface Testing 
with Phantomjs and Casperjs 
ELUNA 2014 Montreal Developing and testing an open source web application
Development: Software ELUNA 2014 
• The Django application framework 
• Programming in Python on Ubuntu Linux 
• Tested with Apache Bench 
• Multiple API’s (OpenLibrary, Google, Summon, 
OpenURL, Worldcat) 
• Oracle SQL, Z39.50 
• Phantomjs, Casperjs 
ELUNA 2014 Montreal Developing and testing an open source web application
Environment: Systems ELUNA 2014 
All of these sources may be accessed in the background to retrieve title, holding, 
status, and other information using API’s, Z39.50, or Oracle SQL. 
SQLPlus query Z39.50 query 
Innovative 
Interfaces 
Sierra 
WRLC 
Z39.50 query 
Holding, item status 
& bibliographic detail 
Holding, item status Holding, item status 
Google Book API Open Library API 360 Link API 
360 LINK 
Book covers, 
full text online 
Journal Coverage date, 
provider 
ILL links for titles not 
held in consortium 
ELUNA 2014 Montreal Developing and testing an open source web application
Request: URL patterns ELUNA 2014 
The application responds to http requests. 
http://findit.library.gwu.edu/ 
item/3171945 
item/3171945.json 
item/3171945/marc.json 
isbn/096139210X 
issn/1448-4404 
oclc/ocm46792617 
...and will compile consortium holdings with their 
real-time availability in a single view 
ELUNA 2014 Montreal Developing and testing an open source web application
Item response example ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
Request: OpenURL ELUNA 2014 
OpenURL request example 
http://findit.library.gwu.edu/item/2388242?ctx_ver=Z39.88-2004 
&ctx_enc=info:ofi/enc:UTF-8 
&rfr_id=info:sid/ProQ:abiglobal 
&rft_val_fmt=info:ofi/fmt:kev:mtx:journal 
&rft.genre=article&rft.jtitle=Library%20Hi%20Tech 
&rft.atitle=Developing%20and%20completing%20a%20library%20mobile 
%20technology%20survey%20to%20create%20a%20user-centered% 
20mobile%20presence 
&rft.au=Becker,%20Danielle%20Andre;Bonadie-Joseph,%20 
Ingrid;Cain,%20Jonathan 
&rft.aulast=Becker&rft.aufirst=Danielle 
&rft.date=2013-10-01 
&rft.volume=31&rft.issue=4&rft.spage=688&rft.isbn=&rft.btitle= 
&rft.title=Library%20Hi%20Tech 
&rft.issn=07378831# 
360 
ELUNA 2014 Montreal Developing and testing an open source web application
OpenURL example ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
API’s ELUNA 2014 
How to use API’s 
• OpenLibrary covers 
• OpenLibrary book 
• Worldcat 
• Google Books 
• 360 Link* 
• Summon Search* 
* Requires subscription key 
ELUNA 2014 Montreal Developing and testing an open source web application
API: OpenLibrary Cover ELUNA 2014 
Covers are displayed when they are available from 
OpenLibrary’s covers API. 
OpenLibrary cover API syntax 
Example: http://covers.openlibrary.org/b/isbn/0521800900-M.jpg 
See: http://openlibrary.org/dev/docs/api/covers 
ELUNA 2014 Montreal Developing and testing an open source web application
ELUNA 2014 
API: OpenLibrary book 
While processing the request we check the 
OpenLibrary to see if a full text is available online. 
If so, we generate a link to the full text. 
Open Library Book API 
See: http://openlibrary.org/dev/docs/api/books 
Example: 
http://openlibrary.org/api/books?format=json&jscmd=data 
&bibkeys=LCCN:11025443 
ELUNA 2014 Montreal Developing and testing an open source web application
API: Worldcat ELUNA 2014 
There was a search by 
/oclc/37478754 
No match found in the 
consortium catalog; 
We show results found in 
Worldcat. 
ELUNA 2014 Montreal Developing and testing an open source web application
API: Worldcat ELUNA 2014 
Worldcat books API syntax 
Example: http://www.worldcat.org/webservices/catalog/content/37478754 
?wskey={your web services key} 
ELUNA 2014 Montreal Developing and testing an open source web application
API: Google books ELUNA 2014 
Google books API syntax 
Example: https://www.googleapis.com/books/v1/volumes?q=lccn:12022977 
&printType=books&maxResults=1&filter=full 
ELUNA 2014 Montreal Developing and testing an open source web application
API: 360 Link ELUNA 2014 
The 360 Link XML API provides 
‘From – to’ date range and 
Database provider name 
From 2003 to present 
Directory of Open Access Journals 
ELUNA 2014 Montreal Developing and testing an open source web application
API: Summon Search ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
API: Summon Search ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
Software repository ELUNA 2014 
• The code is managed with git 
• The ‘about Launchpad page’ at github is 
http://gwu-libraries.github.io/launchpad/ 
• Available on github repository 
https://github.com/gwu-libraries 
• The code is available as open source 
• Updates are released on a regular schedule 
ELUNA 2014 Montreal Developing and testing an open source web application
UI Testing ELUNA 2014 
User Interface Testing 
with 
Phantomjs and Casperjs 
ELUNA 2014 Montreal Developing and testing an open source web application
PhantomJS ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
PhantomJS script ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
PhantomJS result ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS test module ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS with shell script ELUNA 2014 
# Usage: sh issue.sh NNN 
# Description: This script invokes casperjs test on a given file, NNN.js 
# which should be in the current working directory. 
# The target server url is defined in a separate configuration file 
# which should be in the current working directory. 
# The test results are displayed on screen. 
# Test results are also saved in an xml file named log-NNN.xml 
## where NNN is the issue number 
# OK run casper test 
# 
casperjs test $1.js --includes=config.js --xunit=log-$1.xml 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS configuration ELUNA 2014 
// Config_template 
// Use this file to configure a server setting 
// This file should be included when calling casperjs 
// $1.js is the name of the test script file, e.g., 248.js 
// Example: 
// casperjs test $1.js --includes=config.js 
// identity one SERVER path 
// - - - - - - - - - - - - - - - - - - - - - - - - - 
// 
var SERVER='http://gwdev-cummings.wrlc.org'; 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS use case#1 ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script#1 ELUNA 2014 
// m16_003 #555, 569 
// 
// 
casper.test.begin('m16_003 #555, 569 GT location SCS not eligible for CLS', 
2, function suite(test) 
{ 
casper.echo("Test environment: "+SERVER); 
var USECASE='/isbn/9781454816454'; 
var ENTITY=SERVER+USECASE; 
casper.start(ENTITY, function() { 
test.assertTextExists('Basic contract law' , 'page title Basic contract law... found'); 
test.assertTextDoesntExist('CLSReqForm?' , 'Verified there is no Request link.'); 
}).run(function() { 
test.done(); 
}); 
}); 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script#1 result ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS log as XML ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS use case #2 ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script#2 ELUNA 2014 
// m16_001 #473 
// this test employs xPath to locate an id 
casper.test.begin('m16_001 #473 add google analytics to track tab click', 5, function 
suite(test) { 
casper.echo("Test environment: "+SERVER); 
var USECASE='/item/2256589'; 
var ENTITY=SERVER+USECASE; 
var x = require('casper').selectXPath; 
casper.start(ENTITY, function() { 
test.assertTextExists('Sociology and architectural design' , 'page title verified'); 
test.assertSelectorHasText('li', 'Availability'); 
test.assertExists('.nav', 'found a class named "nav"'); 
test.assertExists('.active', 'found a class named "active"'); 
test.assertExists(x('//*[@id="holdings"]'), 'xPath found the holdings div'); 
}).run(function() { 
test.done(); 
}); 
}); 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script#2 result ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS use case#3 ELUNA 2014 
All formats (205) 
.46 seconds 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script#3 ELUNA 2014 
// projects/casperscripts/caspertests/mcgill.js 
// 
casper.test.begin('mcgill', 3, function suite(test) { 
casper.echo("Test environment: "+SERVER); 
var USECASE="ticonderoga"; 
var SUFFIX="&qt=results_page&dblist=638&scope=2&oldscope=2&fq="; 
var ENTITY=SERVER+USECASE+SUFFIX; 
casper.echo("Test: "+ENTITY); 
casper.start(ENTITY, function() { 
test.assertTextExists('Fort Ticonderoga' , 'found title Fort Ticonderoga 
in results'); 
test.assertTextExists('All Formats (205)' , 'Check whether still has 206 
in all formats'); 
test.assertTextExists('.46 seconds' , 'Check whether it took .46 seconds'); 
}).run(function() { 
test.done(); 
}); 
}); 
ELUNA 2014 Montreal Developing and testing an open source web application
CasperJS script #3 result ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
Demo ELUNA 2014 
ELUNA 2014 Montreal Developing and testing an open source web application
Software: Learn more ELUNA 2014 
About Phantomjs 
http://phantomjs.org 
About Casperjs 
https://casperjs.org 
Contact 
Michael Cummings 
Library Systems Coordinator 
The George Washington University Libraries 
michaelc@gwu.edu 
ELUNA 2014 Montreal Developing and testing an open source web application

ELUNA2014: Developing and Testing an open source web application

  • 1.
    Developing and Testingan open source web application ELUNA 2014 Montreal Michael Cummings, GWU
  • 2.
    Agenda ELUNA 2014 Agenda Developing a customized library catalog using API’s User Interface Testing with Phantomjs and Casperjs ELUNA 2014 Montreal Developing and testing an open source web application
  • 3.
    Development: Software ELUNA2014 • The Django application framework • Programming in Python on Ubuntu Linux • Tested with Apache Bench • Multiple API’s (OpenLibrary, Google, Summon, OpenURL, Worldcat) • Oracle SQL, Z39.50 • Phantomjs, Casperjs ELUNA 2014 Montreal Developing and testing an open source web application
  • 4.
    Environment: Systems ELUNA2014 All of these sources may be accessed in the background to retrieve title, holding, status, and other information using API’s, Z39.50, or Oracle SQL. SQLPlus query Z39.50 query Innovative Interfaces Sierra WRLC Z39.50 query Holding, item status & bibliographic detail Holding, item status Holding, item status Google Book API Open Library API 360 Link API 360 LINK Book covers, full text online Journal Coverage date, provider ILL links for titles not held in consortium ELUNA 2014 Montreal Developing and testing an open source web application
  • 5.
    Request: URL patternsELUNA 2014 The application responds to http requests. http://findit.library.gwu.edu/ item/3171945 item/3171945.json item/3171945/marc.json isbn/096139210X issn/1448-4404 oclc/ocm46792617 ...and will compile consortium holdings with their real-time availability in a single view ELUNA 2014 Montreal Developing and testing an open source web application
  • 6.
    Item response exampleELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 7.
    Request: OpenURL ELUNA2014 OpenURL request example http://findit.library.gwu.edu/item/2388242?ctx_ver=Z39.88-2004 &ctx_enc=info:ofi/enc:UTF-8 &rfr_id=info:sid/ProQ:abiglobal &rft_val_fmt=info:ofi/fmt:kev:mtx:journal &rft.genre=article&rft.jtitle=Library%20Hi%20Tech &rft.atitle=Developing%20and%20completing%20a%20library%20mobile %20technology%20survey%20to%20create%20a%20user-centered% 20mobile%20presence &rft.au=Becker,%20Danielle%20Andre;Bonadie-Joseph,%20 Ingrid;Cain,%20Jonathan &rft.aulast=Becker&rft.aufirst=Danielle &rft.date=2013-10-01 &rft.volume=31&rft.issue=4&rft.spage=688&rft.isbn=&rft.btitle= &rft.title=Library%20Hi%20Tech &rft.issn=07378831# 360 ELUNA 2014 Montreal Developing and testing an open source web application
  • 8.
    OpenURL example ELUNA2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 9.
    API’s ELUNA 2014 How to use API’s • OpenLibrary covers • OpenLibrary book • Worldcat • Google Books • 360 Link* • Summon Search* * Requires subscription key ELUNA 2014 Montreal Developing and testing an open source web application
  • 10.
    API: OpenLibrary CoverELUNA 2014 Covers are displayed when they are available from OpenLibrary’s covers API. OpenLibrary cover API syntax Example: http://covers.openlibrary.org/b/isbn/0521800900-M.jpg See: http://openlibrary.org/dev/docs/api/covers ELUNA 2014 Montreal Developing and testing an open source web application
  • 11.
    ELUNA 2014 API:OpenLibrary book While processing the request we check the OpenLibrary to see if a full text is available online. If so, we generate a link to the full text. Open Library Book API See: http://openlibrary.org/dev/docs/api/books Example: http://openlibrary.org/api/books?format=json&jscmd=data &bibkeys=LCCN:11025443 ELUNA 2014 Montreal Developing and testing an open source web application
  • 12.
    API: Worldcat ELUNA2014 There was a search by /oclc/37478754 No match found in the consortium catalog; We show results found in Worldcat. ELUNA 2014 Montreal Developing and testing an open source web application
  • 13.
    API: Worldcat ELUNA2014 Worldcat books API syntax Example: http://www.worldcat.org/webservices/catalog/content/37478754 ?wskey={your web services key} ELUNA 2014 Montreal Developing and testing an open source web application
  • 14.
    API: Google booksELUNA 2014 Google books API syntax Example: https://www.googleapis.com/books/v1/volumes?q=lccn:12022977 &printType=books&maxResults=1&filter=full ELUNA 2014 Montreal Developing and testing an open source web application
  • 15.
    API: 360 LinkELUNA 2014 The 360 Link XML API provides ‘From – to’ date range and Database provider name From 2003 to present Directory of Open Access Journals ELUNA 2014 Montreal Developing and testing an open source web application
  • 16.
    API: Summon SearchELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 17.
    API: Summon SearchELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 18.
    Software repository ELUNA2014 • The code is managed with git • The ‘about Launchpad page’ at github is http://gwu-libraries.github.io/launchpad/ • Available on github repository https://github.com/gwu-libraries • The code is available as open source • Updates are released on a regular schedule ELUNA 2014 Montreal Developing and testing an open source web application
  • 19.
    UI Testing ELUNA2014 User Interface Testing with Phantomjs and Casperjs ELUNA 2014 Montreal Developing and testing an open source web application
  • 20.
    PhantomJS ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 21.
    PhantomJS script ELUNA2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 22.
    PhantomJS result ELUNA2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 23.
    CasperJS ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 24.
    CasperJS test moduleELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 25.
    CasperJS with shellscript ELUNA 2014 # Usage: sh issue.sh NNN # Description: This script invokes casperjs test on a given file, NNN.js # which should be in the current working directory. # The target server url is defined in a separate configuration file # which should be in the current working directory. # The test results are displayed on screen. # Test results are also saved in an xml file named log-NNN.xml ## where NNN is the issue number # OK run casper test # casperjs test $1.js --includes=config.js --xunit=log-$1.xml ELUNA 2014 Montreal Developing and testing an open source web application
  • 26.
    CasperJS configuration ELUNA2014 // Config_template // Use this file to configure a server setting // This file should be included when calling casperjs // $1.js is the name of the test script file, e.g., 248.js // Example: // casperjs test $1.js --includes=config.js // identity one SERVER path // - - - - - - - - - - - - - - - - - - - - - - - - - // var SERVER='http://gwdev-cummings.wrlc.org'; ELUNA 2014 Montreal Developing and testing an open source web application
  • 27.
    CasperJS use case#1ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 28.
    CasperJS script#1 ELUNA2014 // m16_003 #555, 569 // // casper.test.begin('m16_003 #555, 569 GT location SCS not eligible for CLS', 2, function suite(test) { casper.echo("Test environment: "+SERVER); var USECASE='/isbn/9781454816454'; var ENTITY=SERVER+USECASE; casper.start(ENTITY, function() { test.assertTextExists('Basic contract law' , 'page title Basic contract law... found'); test.assertTextDoesntExist('CLSReqForm?' , 'Verified there is no Request link.'); }).run(function() { test.done(); }); }); ELUNA 2014 Montreal Developing and testing an open source web application
  • 29.
    CasperJS script#1 resultELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 30.
    CasperJS log asXML ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 31.
    CasperJS use case#2 ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 32.
    CasperJS script#2 ELUNA2014 // m16_001 #473 // this test employs xPath to locate an id casper.test.begin('m16_001 #473 add google analytics to track tab click', 5, function suite(test) { casper.echo("Test environment: "+SERVER); var USECASE='/item/2256589'; var ENTITY=SERVER+USECASE; var x = require('casper').selectXPath; casper.start(ENTITY, function() { test.assertTextExists('Sociology and architectural design' , 'page title verified'); test.assertSelectorHasText('li', 'Availability'); test.assertExists('.nav', 'found a class named "nav"'); test.assertExists('.active', 'found a class named "active"'); test.assertExists(x('//*[@id="holdings"]'), 'xPath found the holdings div'); }).run(function() { test.done(); }); }); ELUNA 2014 Montreal Developing and testing an open source web application
  • 33.
    CasperJS script#2 resultELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 34.
    CasperJS use case#3ELUNA 2014 All formats (205) .46 seconds ELUNA 2014 Montreal Developing and testing an open source web application
  • 35.
    CasperJS script#3 ELUNA2014 // projects/casperscripts/caspertests/mcgill.js // casper.test.begin('mcgill', 3, function suite(test) { casper.echo("Test environment: "+SERVER); var USECASE="ticonderoga"; var SUFFIX="&qt=results_page&dblist=638&scope=2&oldscope=2&fq="; var ENTITY=SERVER+USECASE+SUFFIX; casper.echo("Test: "+ENTITY); casper.start(ENTITY, function() { test.assertTextExists('Fort Ticonderoga' , 'found title Fort Ticonderoga in results'); test.assertTextExists('All Formats (205)' , 'Check whether still has 206 in all formats'); test.assertTextExists('.46 seconds' , 'Check whether it took .46 seconds'); }).run(function() { test.done(); }); }); ELUNA 2014 Montreal Developing and testing an open source web application
  • 36.
    CasperJS script #3result ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 37.
    Demo ELUNA 2014 ELUNA 2014 Montreal Developing and testing an open source web application
  • 38.
    Software: Learn moreELUNA 2014 About Phantomjs http://phantomjs.org About Casperjs https://casperjs.org Contact Michael Cummings Library Systems Coordinator The George Washington University Libraries michaelc@gwu.edu ELUNA 2014 Montreal Developing and testing an open source web application

Editor's Notes

  • #4 GW has been using SQLPlus in a Linux environment for a couple of years. “Using Oracle SQL*Plus to query Voyager in a Linux environment” was the topic of the presenter’s talk at ELUNA in 2012. A link to the presentation is provided later in these slides. We were able to do a rapid prototype of our concept using SQLPlus and CGI-Perl. We then converted the code to a more modern web application framework. Django manages cache, connections, and other aspects quite well. Normally you can model your database and then use Django to perform queries without writing SQL. However, due to the large Voyager schema and the fact that we already had the SQL from our prototype, we include those queries in our code. Python has many advantages, including modules that developers can import – such as pymarc for parsing MARC records. We stress tested the code with Apache Bench in coordination with the Voyager system administrator.
  • #5 The WRLC maintains a consortium Voyager catalog of approximately 12 million bib records including George Washington University, American, Catholic, District of Columbia, Gallaudet, George Mason (copy of bib), Georgetown (copy of bib), Howard, and Marymount. Our program retrieves bibliographic, holding, and item status data from the WRLC Voyager using SQLPlus. Georgetown has their own ILS, III Sierra, which we query using the Z39.50 protocol in order to obtain holding and item status. George Mason has a hosted instance of Voyager that we query using the Z39.50 protocol in order to obtain holding and item status. We use API’s to retrieve other information, which is explained in the following pages.
  • #6 Using the word ‘item’ in the URL is sort of a misnomer,. It is the Voyager, or Millenium, bibid not the ‘item’ id. Each title has an item page. The other URL patterns are for look-up purposes. If a match is found based on one of the other standard identifiers, the page displayed will show the bib id in place of the standard number in the URL.
  • #11 Book covers are provided via OpenLibrary’s image API. This is a free service. OpenLibrary cover API See: http://openlibrary.org/dev/docs/api/covers Example: http://covers.openlibrary.org/b/isbn/0521800900-M.jpg
  • #12 While processing the request we check the OpenLibrary to see if a full text is available online. If so, we generate a link to the full text. OpenLibrary / Internet archive full text is available for thousands of books. The OpenLibrary API accepts queries based on standard numbers LCCN, OCLC, and OpenLibrary ID. Open Library Book API See: http://openlibrary.org/dev/docs/api/books Example: http://openlibrary.org/api/books?format=json&jscmd=data&bibkeys=LCCN:11025443
  • #13 If we receive a request for an OCLC which doesn’t match a book in the library catalog, we use the Worldcat API to find a match. If foud, we provide basic bibliographic info, and a link for the patron to request the book through interlibrary loan.
  • #15 https://www.googleapis.com/books/v1/volumes?q=lccn:12022977&printType=books&maxResults=1&filter=full
  • #16 360 Link API provides coverage details. Often there are several providers with access to a different range of dates for the same publications. This API requires a subscriber key for Proquest / Serials Solutions
  • #17 Proquest / Summon, like Exlibris Voyager and other products, has a fairly extensive set of API’s We have started to use the search API which returns results like this… and we display it in our version of a Discovery Catalog view.
  • #18 Under development. Planned implementation for summer 2014. The results are from Serials Solutions / Proquest Summon, scoped to items in the library catalog.
  • #19 The code is officially available as open source.
  • #21 Download and this first
  • #22 cd /home/cummings/projects/phantom/phantom_v1.9/phantomjs/examples PS1=“Qui? “ cat pizza.js
  • #23 Phantomjs pizza.js | more Also … weather.js tweets.js newseum direction.js montreal boston
  • #24 Casper home page
  • #28 There should not be a link in the Consortium Loan column
  • #33 5 tests using css elements instead of HTML page content
  • #38 If we have an ssh connection… cd projects/launchpad-autotest/ sh m14.sh
  • #39  From Voyager to your website: Using Linux Shell scripts and Oracle SQL*Plus to generate web pages. https://github.com/cummingsm/VoyagerELUNA2012