Testing the Web Service

an article added by: Sonja Lande at 06012007


In: Categories » » AJAX » Testing the Web Service

With the Web service created and running, you could go ahead and start coding the client. But that would be the incorrect approach. One of the things that has changed with Web services and SOA is that the client and server communicate using a contract. Previously, client/server applications communicated using a protocol that the developers decided upon. If the developers needed a new method or piece of information, that alteration would be made. It was not a big deal to make changes on the fly. With Web services and SOA, that is no longer the case. With the advent of Web services and SOA, we have the ability to define a contract that can be reused and shared by other parties. If there is one major advantage to SOA, it is its ability to seamlessly share data.

Let’s put this into another context. Imagine you own a pizza restaurant, with take-out orders, online orders, and wait staff to take orders from onsite customers. So customers can order a pizza in a few different ways, and each way probably has a completely different ordering system. In fact, it’s questionable that you even need wait staff to take an order in the first place. In this day and age, you could put a touch screen on each table and let the customers order their pizza directly. Then as the order is fulfilled, somebody brings it to the table. Or how about enabling customers to order a pizza online, and then indicate that they want to eat it in the restaurant at a certain time? The system could reserve a table for the customers, making it possible for them to take a seat at their reserved table when they enter the restaurant and have their meal served immediately. But wouldn’t that ruin the experience of going to restaurant? In my opinion, it wouldn’t going to restaurant can be a pretty hectic experience. This pizza restaurant example illustrates the client/server architectures of days past, with wait staff taking the customers’ orders. SOA, on the other hand, represents a uniform pizza ordering system regardless of the entry device being used (in person, online, by cell phone, etc.). After all, is a pizza ordered through the wait staff any different from a pizza ordered online? The answer is no.

Having your Web service used in multiple contexts poses a challenge in that the contract must be extensively tested. If you do not extensively test the Web service, you could cause problems. For example, imagine you created a blog Web service feed that had a minor bug. End developers who use your feed encounter the bug and see that it’s minor. To save hassle, they do a quick little workaround. Workarounds are dangerous because they assume things will happen a certain way. You give your feed to other third parties who don’t encounter the minor bug for one reason or another. As time passes, a client receives the feed, and they encounter the bug. Unlike everybody else, they send an email about the bug and ask it to be fixed. So what do you do when you receive the bug notification? Do you fix the bug or not? The answer should be that you fix the bug, but the reality is that if the bug is minor, the bug fix could cause working code to stop working. This is why testing aWeb service is so critical: by testing, you minimize the chance of future problems. Web service testing has to be exhaustive and extensive; it is not aminor undertaking. In the case of the blog application, an online testing service can make your life easier.

The feed validator makes sure that the Atom feed is correct, but the feed validator does not validate if the contents of the feed are correct. That is another level of testing and validation that would be necessary. The feed validator makes it possible to decouple the client from the server. Having the client and server decoupled makes it simpler to introduce changes in the overall architecture because you can make the changes gradually. Going back to the original architecture of the blog architecture, imagine changing the structure of how blog entries are displayed. Because the client and server code are intertwined, the developer might be tempted to tweak the server code. However, the server generates three different formats, and you have to wonder if the tweaks will have to be added to the other two formats. Using a single feed that is validated, client programmers have no choice but to tweak their own code. Client programmers cannot touch the code of the server and hence cannot introduce unintended bugs. I mentioned that testing an interface requires an exhaustive and extensive set of tests the feed validator provides just that. But not all Web services fit into the category of a blog application, and you have to implement your own testing infrastructure. Ideally, you want an architecture like a feed validator, because it makes testing a snap. But a feed validator is a big application, and you probably don’t have enough time to write such a complicated piece of code.

Experience has taught me that the easiest way to write tests quickly and cleanly is to use a programming language that has support for test-driven development techniques (e.g., NUnit or JUnit). You can also use a dynamic language such as Python or Ruby. Something else experience has taught me is to not reinvent the wheel. If a protocol, XML grammar, or implementation already exists, then use that. Don’t try to come up with new ways of doing the same old thing you will only complicate your life. It might be a bit more complex initially to adhere to the standard, but in the long run you’ll have fewer concerns. For example, by sticking to the Atom feed in the blog architecture, you can use a publicly available tool to test the application. It doesn’t require writing any test code; you just have to write a few test scripts to call the Feed Validator Web site.

Implementing the Client Implementing a client in an Ajax context always involves two steps: loading the document and executing the document. In the case of the blog application, there is no need for the client to intervene, so the document should be executed once it has been loaded. In JavaScript, the body.onload event is fired once the document has been completely loaded. It is very important that you use the body.onload event and not some script that is executed while the document is being loaded. While the document is being loaded, it is considered incomplete, so referencing HTML elements on the document might be successful, but it might not. When using the body.onload event, you can be sure that the document has been completely loaded and every element that needs referencing is available.

When the body.onload event is fired and the content is loaded, the content can be processed and injected into the HTML document. To the user, this two-step process seems like a single page load rather than a two-step process (if both the client and server have enough bandwidth). If the two-step loading does not execute fast enough, you will notice a slight flicker, indicating that some content has been loaded and arranged. The end result is the same, and the client is presented with a single document that presents itself as a single application. In a nutshell, this process is no different than building a traditional client/server or n-tier application, except open standards and a dynamic programming language environment are used. With the overall client-side architecture covered, let’s dig a bit deeper into each of the steps.

Loading the Document As mentioned previously, the first step is loading the document. If we compare loading the document with loading a traditional application, what is happening is that the browser is like an operating system preparing the memory, modules, and foundation for the program to execute. So, for example, if we are loading the document, the following code will instantiate the XMLHttpRequest object:

   getTransport: function() {
   return Try.these(
   function() {return new  ActiveXObject('Msxml2.XMLHTTP')},
   function() {return new  ActiveXObject('Microsoft.XMLHTTP')},
   function() {return new XMLHttpRequest()}
   ) || false;
 },

The source of the code is not important because many Ajax libraries do the same thing. Essentially, when the code is executed, it tries to figure out which browser it’s dealing with so it can return at runtime the correct way to instantiate the XMLHttpRequest object. I contend this is the wrong approach, and it uses the traditional executable loading and running mentality. When an operating system loads a traditional program, the variables, modules, and so forth are initialized before program execution. While a browser loads source code, the browser has the ability to execute JavaScript code. With this in mind, you could write the following code:

   if (window.ActiveXObject) {
   FactoryXMLHttpRequest = function() {
   return new ActiveXObject("Microsoft.XMLHTTP");
   }
   }
   else if (window.XMLHttpRequest) {
   FactoryXMLHttpRequest = function() {
   return new XMLHttpRequest();
   }
 }

In the example, there is no function, just a decision. The decision is if the browser loading the document is Internet Explorer, then define the FactoryXMLHttpRequest function to instantiate ActiveXObject. If the browser is not Internet Explorer, then define the FactoryXMLHttpRequest function to instantiate the XMLHttpRequest object directly. The second source code initialization example is not as flexible during the runtime because the defined FactoryXMLHttpRequest function can only instantiate the XMLHttpRequest object as it was defined when the document was loaded. Even though this seems like a drawback, you have to ask yourself what the chances are that the loaded document will be moved byte by byte to another browser type. The answer is that there is no chance this will happen, as it is not possible.

The advantage of the second source code example is that functionality can be tuned to the browser it is executing on while the document is being loaded. In the example, the tuning was based on the browser. There are other ways to tune and reasons for tuning your application, such as figuring out the language or dimensions of the browser. Tuning has the advantage that you don’t need to carry around the executable baggage that is associated with decisions made at runtime. This is an important factor to remember, as you can reduce the runtime footprint of your code by preconfiguring the application during document loading. But there’s one big disadvantage to using a document loading–generated configuration having to do with serialization. Previous articles demonstrated how to use JavaScript serialization to generate proxies or mixins. If a document-loaded configuration is serialized and stored on an HTTP server, and then it’s loaded at a later point in time using a different browser, an error will be generated.

The rule of thumb is that when there is an advantage in terms of performance or resources, use the document-loaded configuration. Use the general runtime approach, which includes a runtime decision-making process, if there’s a slight chance that the code will be serialized. And for those situations where it really does not matter one way or the other, use whatever makes sense for you.

Executing the Document After the document has been loaded, the body.onload event is triggered and the associated code is executed. In HTML terms, the code looks as follows. Note that the code has been abbreviated for clarity.

   Source: /client/index.html
   function  LoadAtomFeed() {
   var  asynchronous = new Asynchronous();
   asynchronous.settings  = {
   onComplete  : function(xmlhttp) {
   parseAtom(  xmlhttp.responseXML);
   flexbox.update();
   }
   }
   asynchronous.get("/services/blog/entries/current");
   }
   function InitializePage() {
   // Extra initialization code cut out relating  to
   LoadAtomFeed();
   }
 </script>
 </head>
 <body onload="InitializePage()">
 <h1>Welcome To BloggerJacks</h1>
 <!-- Document section -->
 </body>
 </html>

Consider the bold code. When the document is loaded, the body.onload event is fired. That calls the InitializePage function, which in turn calls the LoadAtomFeed function. In the implementation of LoadAtomFeed, the Asynchronous class is instantiated, which in turn instantiates the XMLHttpRequest object.

legal notice

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

Useful tools and features

Link to this article from your page    Send this article to you or to a friend
If you like this article (tutorial), please link to it from your web page using the information above.

related articles

1. Understanding the Definition and Philosophy of Ajax
The focus of this article is to provide solutions to some common, general problems and questions that are bound to arise before or during development of Asynchronous JavaScript and XML (Ajax) and Representational State Transfer (REST) applications. These common questions are not always technical in nature, often leaning more toward theory or philosophy of development. The problem with these kinds of questions is that once you begin to think about them, you keep going in a circle and end up where you star...

2. Understanding the Definition and Philosophy of Web Services and SOA
Understanding the Definition and Philosophy of Web Services and SOA Wikipedia offers the following definition of Web services:4 The W3C defines aWeb service as a software system designed to support interoperable machine-to-machine interaction over a network. This definition encompasses many different systems, but in common usage the term refers to those services that use SOAPformatted XML envelopes and have their interfaces described by WSDL. For ex...

3. Understanding the Definition and Philosophy of REST
Understanding the Definition and Philosophy of REST REST is a controversial topic among Web service enthusiasts, because it’s considered to stand for the opposite of what Web services and SOA are trying to achieve. The problem with this thinking is that REST is not in contradiction with the abstract definition of SOA and Web services. REST is in contradiction with technologies such as SOAP, WSDL, and WS-* specifications. The following offers a quick definition of REST:...

4. The Easiest Way to Get Started with Ajax and REST
The Easiest Way to Get Started with Ajax and REST Problem You want to know the best way to get started with writing Ajax and REST. Solution When developing an Ajax and REST application, you must decide on the tools and frameworks you’ll use. The choice is simple: Use whatever you’re using today, and write some Ajax applications. You don’t need to change the tools you’re using today. Whether you’re using ASP.NET, JavaServer Pages (JSP), PHP, Ruby, or Python, you...

5. Testing a Dynamic Contract with Ajax
Coding the Contract Using Test-Driven Development Techniques Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally...

6. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...

7. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...