Channels ▼
RSS

Tools

Testing Service Oriented Architectures

Source Code Accompanies This Article. Download It Now.


A Test Harness in Ruby

To test some of these ideas, my team implemented a simple record-and-playback style test harness in Ruby (www2.ruby-lang.org/en/). We decided that Ruby's dynamic programming and metaprogramming features would be useful in creating a harness that could add methods declaratively at runtime. Since our team consisted of Java developers trying Ruby for the first time, we decided to use JRuby (jruby.codehaus.org). This let us incorporate well-understood Java frameworks from within the Ruby source.

Using SOAP4R (dev.ctor.org/soap4r), we wrote a SOAP Client. Data was then recorded from an existing Apache Axis2 service. The output was saved using YAML (www.yaml.org), a powerful human-readable data serialization mechanism available with Ruby implementations. We also used SOAP4R to create a standalone SOAP Server. Methods to be tested and the corresponding results were maintained as key-value pairs in a Java properties file. The format of each key-value pair is:

methodname_param1param2...    paramN=recorded_response.yml

If desired, we could have extended the format to refer to specific service URIs as well. Finally, we added methods at runtime using Ruby's metaprogramming facilities. Example 1 created the methods. The Java classes (Properties, FileInputStream) are leveraged by way of JRuby. Example 2 presents the corresponding client code used to record data from the web service.

#read the methods and responses from test.properties
fis = FileInputStream.new("test.properties")
          @properties = Properties.new
          @properties.load(fis)
          fis.close
          keys = @properties.keys
#add methods to return the recorded response
          keys.each do |key|
            puts "Adding method " + key.to_s
            add_method(self,key.to_s, Object.new)
            self.class.send('define_method', key.to_s) { |*args|
               if (@properties.containsKey(key.to_s))
                 value= @properties.get(key)
                 puts "Found operation " + key.to_s + " 
                                  with value " + value.to_s
#retrieve the data from the saved result
                 if (value)
                   if (value.rindex('.yml') > 0)
                     data = YAML::load_file(value)
                     return data
                   else
                     file = File.new(value)
                     data = file.readlines
                     file.close
                     return data
                   end
                 end
               end
               }
            end

Example 1: Code fragment to add methods.

While this example is simple, it provides the skeleton of a test harness for services. With moderate effort, you can extend it to encompass multiple services with multiple methods. Consequently, the server can be used to create a boundary of services to be invoked by the service(s) under study.

driver = SOAP::RPC::Driver.new(
    'http://localhost:8080/axis2/services/WeatherService',
    'http://ws.apache.org/axis2')  
#driver = SOAP::RPC::Driver.new(
    'http://localhost:9080/','urn:weatherSoapServer')
driver.add_method('getWeather')

file = File.new('getweather.yml','w')
YAML.dump(driver.getWeather,file)
file.close

Example 2: Client code to store service output.

To the best of my knowledge, there are two commercial off-the-shelf solutions that provide this sort of functionality exist—iTKO's LISA (www.itko.com) and AmberPoint's Validation (www.amberpoint.com/products/validation.shtml). Both provide Service Virtualization to varying degrees. While Amberpoint's solution is a development time record-and-playback utility, iTKO's solution also has elements for continuous testing of services.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video