Your SlideShare is downloading. ×
Structured Functional Automated Web Service Testing
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Structured Functional Automated Web Service Testing

1,374

Published on

This presentation gives an answer on why you should use a programming language for automating web service tests

This presentation gives an answer on why you should use a programming language for automating web service tests

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,374
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Web Services make it possible to expose application functionality to the out-side world using a standardized protocol. It’s more frequently used these days to enable direct interaction between applications, so multiple applications can use the same web services. It has to be good! In this track you will see how you can develop a structured framework to create maintainable/reusable functional automated web service tests.
  • Technisch test specialistIk geef twee testautomatiserings trainingenEn daarnaast ben ik betrokken bij enkele innovatie projecten binnen polteqTot slot onderhoud ik 2 blogs:Op selenium.polteq.com staan Selenium gerelateerde tutorialsOp mijn persoonlijk blog staan test-gerelateerde artikellen
  • http://www.slideshare.net/cesare.pautasso/some-rest-design-patterns-and-antipatterns?from_search=4http://www.autotestguy.com/archives/design_patterns/index.htmlDesign Patterns -> have to researchClient c = Client.create(); WebResource w = c.resource("http://host/path"); String s = w.header("name", "value").get(String.class); or you can use client filter as well:          Client c = Client.create();          c.addFilter(new ClientFilter() {              @Override              public ClientResponse handle(ClientRequestcr) throws ClientHandlerException {                  cr.getHeaders(); // do what you want                  return getNext().handle(cr);              }          });
  • http://www.slideshare.net/cesare.pautasso/some-rest-design-patterns-and-antipatterns?from_search=4http://www.autotestguy.com/archives/design_patterns/index.htmlDesign Patterns -> have to researchClient c = Client.create(); WebResource w = c.resource("http://host/path"); String s = w.header("name", "value").get(String.class); or you can use client filter as well:          Client c = Client.create();          c.addFilter(new ClientFilter() {              @Override              public ClientResponse handle(ClientRequestcr) throws ClientHandlerException {                  cr.getHeaders(); // do what you want                  return getNext().handle(cr);              }          });
  • Application contains all business logic and can access the database directly.If you build a second application with more-or-less the same functionality, then you need to copy all businnes logic.
  • By introducing a web service based archticture we try to make it more scalable and accesible for any application type
  • By introducing a web service based archticture we try to make it more scalable and accesible for any application type
  • By introducing a web service based archticture we try to make it more scalable and accesible for any application type
  • By introducing a web service based archticture we try to make it more scalable and accesible for any application type
  • By introducing a web service based archticture we try to make it more scalable and accesible for any application type
  • Application contains less business logic. It’s split over multiple services.There is a agreement on the messages which can be send. The response formats are also known.
  • Application contains less business logic. It’s split over multiple services.There is a agreement on the messages which can be send. The response formats are also known.
  • Why not using Jmeter:Hard to perform pre/post conditionsHard to create maintainable scriptsHard to combin tests (Use webservice and verify on website)Hard to make complex asertions (complex JSON objects)Less flexibility in creating test suites
  • http://www.slideshare.net/cesare.pautasso/some-rest-design-patterns-and-antipatterns?from_search=4http://www.autotestguy.com/archives/design_patterns/index.htmlDesign Patterns -> have to researchClient c = Client.create(); WebResource w = c.resource("http://host/path"); String s = w.header("name", "value").get(String.class); or you can use client filter as well:          Client c = Client.create();          c.addFilter(new ClientFilter() {              @Override              public ClientResponse handle(ClientRequestcr) throws ClientHandlerException {                  cr.getHeaders(); // do what you want                  return getNext().handle(cr);              }          });
  • NS applicationImagine you work for a Dutch Railway company. They decided to develop a public API, so developers can embed railway information into their application.
  • NS applicationImagine you work for a Dutch Railway company. They decided to develop a public API, so developers can embed railway information into their application.
  • Transcript

    • 1. Structured Functional Automated WebService TestingRoy de Kleijn
    • 2. Who am I ?• Technical Test Consultant• Trainer test automation• Involved in R&D activities• Blogs:– http://selenium.polteq.com– http://www.rdekleijn.nl
    • 3. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    • 4. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    • 5. What is a Web Service ?A Web service is a software component that can beaccessed by another application (such as a client, aserver or another Web service) through the use ofgenerally available, ubiquitous protocols andtransports, such as Hypertext Transport Protocol(HTTP).[Gartner]
    • 6. Architecture - conventionalapplicationDB
    • 7. Web Service Based Architecture• Scalable
    • 8. Web Service Based Architecture• Scalable• Support for any application type
    • 9. Web Service Based Architecture• Scalable• Support for any application type• Language independent
    • 10. Web Service Based Architecture• Scalable• Support for any application type• Language independent• Central business logic
    • 11. Web Service Based Architecture• Scalable• Support for any application type• Language independent• Central business logic• Standardised integration
    • 12. Different types• Protocols: WSDL / SOAP / REST
    • 13. Different types• Protocols: WSDL / SOAP / REST• REST (Representational State Transfer)– Defined by HTTP interface
    • 14. Different types• Protocols: WSDL / SOAP / REST• REST (Representational State Transfer)– Defined by HTTP interface– Support of basic application methods (CRUD):• POST -> create new resource• GET -> retrieve resources• PUT -> replace existing resource• Delete -> remove a resource
    • 15. Architecture - SOAapplication
    • 16. Architecture - SOAapplication DBService1Service2Service3
    • 17. Architecture - SOADesktopapplicationMobileapplicationThird-partyapplication
    • 18. Architecture - SOADesktopapplicationMobileapplicationThird-partyapplicationDBService1Service2Service3Service4Third-party
    • 19. How it works...• Request messages are send to a specific endpoint• Messages are mostly XML or JSON fragments• Client can optionally set headers
    • 20. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    • 21. Benefits for a tester• Less brittle tests– No GUI involved, no browser time-outs
    • 22. Benefits for a tester• Less brittle tests– No GUI involved, no browser time-outs• Testing can start in an early phase
    • 23. Benefits for a tester• Less brittle tests– No GUI involved, no browser time-outs• Testing can start in an early phase• No access to the code required (might be benefitialthough)
    • 24. Testing PyramidUISERVICEUNITDevelopers
    • 25. Testing PyramidUISERVICEUNITAutomated UI TestsAutomated API TestsAutomated Unit TestsDevelopers
    • 26. Testing PyramidUISERVICEUNITAutomated UI TestsAutomated API TestsAutomated Unit TestsCompoundIsolationDevelopers
    • 27. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    • 28. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    • 29. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    • 30. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    • 31. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    • 32. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    • 33. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    • 34. Testing a Web Service• Pitfalls• General advice• Tools you can use
    • 35. Pitfalls• Using performance test tools
    • 36. Pitfalls• Using performance test tools– Hard to use pre/post conditions
    • 37. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts
    • 38. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts– Hard to combine testtypes
    • 39. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts– Hard to combine testtypes– Hard to make complex assertions
    • 40. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts– Hard to combine testtypes– Hard to make complex assertions– Limited flexibility in creating test suites
    • 41. General advice• Use a programming language
    • 42. General advice• Use a programming language– IDE features• Auto-completion, refactoring
    • 43. General advice• Use a programming language– IDE features• Auto-completion, refactoring– Apply design patterns• Make it maintainable and DRY (don’t repeat yourself)
    • 44. General advice• Use a programming language– IDE features• Auto-completion, refactoring– Apply design patterns• Make it maintainable and DRY (don’t repeat yourself)– Flexible pre/post conditions
    • 45. General advice• Use a programming language– IDE features• Auto-completion, refactoring– Apply design patterns• Make it maintainable and DRY (don’t repeat yourself)– Flexible pre/post conditions– Combine your Selenium tests with web service tests
    • 46. Tools you can use• Jersey– Making REST requests• Jackson– JSON processor• JAXB– XML processor• JsonPath– Extract parts of a JSON document
    • 47. Tools you can use• TestNG– Java testing framework• XMLUnit– Assertions for XML, validate against XSD schema• Hamcrest– General matcher library
    • 48. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    • 49. Case 1Imagine you work for a Dutch Railway company. Theydecide to create a public API, so developers can embedrailway information into their application.You (as a tester) have to test the service.
    • 50. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 51. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 52. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 53. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 54. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 55. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 56. Create a GET requestClient client = Client.create();WebResource webResource =client.resource("http://webservices.ns.nl");MultivaluedMap<String, String> params = newMultivaluedMapImpl();params.add("station", "ut");ClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").get(ClientResponse.class);if(response.getStatus() != 200) {throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());}System.out.println(response.getEntity(String.class));Output: Failed : HTTP error code : 401
    • 57. Set request headersBasic AuthenticationClient client = Client.create();client.addFilter(new HTTPBasicAuthFilter("username","password"));Other headersClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").header("key", "value").get(ClientResponse.class);
    • 58. Set request headersBasic AuthenticationClient client = Client.create();client.addFilter(new HTTPBasicAuthFilter("username","password"));Other headersClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").header("key", "value").get(ClientResponse.class);
    • 59. Set request headersBasic AuthenticationClient client = Client.create();client.addFilter(new HTTPBasicAuthFilter("username","password"));Other headersClientResponse response = webResource.path("ns-api-avt").queryParams(params).accept("text/xml").header("key", "value").get(ClientResponse.class);
    • 60. Case 2Imagine you have to control a relatively difficult XML-string.
    • 61. XML-response<ActueleVertrekTijden><VertrekkendeTrein><RitNummer>3146</RitNummer><VertrekTijd>2013-06-13T14:28:00+0200</VertrekTijd><EindBestemming>Schiphol</EindBestemming><TreinSoort>Intercity</TreinSoort><RouteTekst>Bijlmer ArenA, Adam Zuid</RouteTekst><Vervoerder>NS</Vervoerder><VertrekSpoor wijziging="true">5</VertrekSpoor></VertrekkendeTrein>........</ActueleVertrekTijden>
    • 62. XML-response<ActueleVertrekTijden><VertrekkendeTrein><RitNummer>3146</RitNummer><VertrekTijd>2013-06-13T14:28:00+0200</VertrekTijd><EindBestemming>Schiphol</EindBestemming><TreinSoort>Intercity</TreinSoort><RouteTekst>Bijlmer ArenA, Adam Zuid</RouteTekst><Vervoerder>NS</Vervoerder><VertrekSpoor wijziging="true">5</VertrekSpoor></VertrekkendeTrein>........</ActueleVertrekTijden>
    • 63. XML-response<ActueleVertrekTijden><VertrekkendeTrein><RitNummer>3146</RitNummer><VertrekTijd>2013-06-13T14:28:00+0200</VertrekTijd><EindBestemming>Schiphol</EindBestemming><TreinSoort>Intercity</TreinSoort><RouteTekst>Bijlmer ArenA, Adam Zuid</RouteTekst><Vervoerder>NS</Vervoerder><VertrekSpoor wijziging="true">5</VertrekSpoor></VertrekkendeTrein>........</ActueleVertrekTijden>
    • 64. XML-response<ActueleVertrekTijden><VertrekkendeTrein><RitNummer>3146</RitNummer><VertrekTijd>2013-06-13T14:28:00+0200</VertrekTijd><EindBestemming>Schiphol</EindBestemming><TreinSoort>Intercity</TreinSoort><RouteTekst>Bijlmer ArenA, Adam Zuid</RouteTekst><Vervoerder>NS</Vervoerder><VertrekSpoor wijziging="true">5</VertrekSpoor></VertrekkendeTrein>........</ActueleVertrekTijden>
    • 65. Create POJO (1)POJO = Plain Old Java Object (nothing special)- Create a class- Implement fields (corresponding to XML elements)- Generate getters/setters- Map Getters to XML elements- By annotationsIn eclipse:Right-click on the class file -> Source -> Generate Getters/Setters
    • 66. Create POJO (2)@XmlRootElement(name = "ActueleVertrekTijden")public class ActueleVertrekTijden {private List<VertrekkendeTrein> vertrekkendeTrein;@XmlElement(name = "VertrekkendeTrein")public List<VertrekkendeTrein> getVertrekkendeTrein() {return vertrekkendeTrein;}public void setVertrekkendeTrein(List<VertrekkendeTrein>vertrekkendeTrein) {this.vertrekkendeTrein = vertrekkendeTrein;}}
    • 67. Create POJO (2)@XmlRootElement(name = "ActueleVertrekTijden")public class ActueleVertrekTijden {private List<VertrekkendeTrein> vertrekkendeTrein;@XmlElement(name = "VertrekkendeTrein")public List<VertrekkendeTrein> getVertrekkendeTrein() {return vertrekkendeTrein;}public void setVertrekkendeTrein(List<VertrekkendeTrein>vertrekkendeTrein) {this.vertrekkendeTrein = vertrekkendeTrein;}}
    • 68. Create POJO (2)@XmlRootElement(name = "ActueleVertrekTijden")public class ActueleVertrekTijden {private List<VertrekkendeTrein> vertrekkendeTrein;@XmlElement(name = "VertrekkendeTrein")public List<VertrekkendeTrein> getVertrekkendeTrein() {return vertrekkendeTrein;}public void setVertrekkendeTrein(List<VertrekkendeTrein>vertrekkendeTrein) {this.vertrekkendeTrein = vertrekkendeTrein;}}
    • 69. Create POJO (3)public class VertrekkendeTrein {private int ritNummer;private String vertrekTijd;private String eindBestemming;private String treinSoort;private String routeTekst;private String vervoerder;private String vertrekSpoor;@XmlElement(name = "RitNummer")public int getRitNummer() {return ritNummer;}public void setRitNummer(int ritNummer) {this.ritNummer = ritNummer;}
    • 70. Create POJO (3)public class VertrekkendeTrein {private int ritNummer;private String vertrekTijd;private String eindBestemming;private String treinSoort;private String routeTekst;private String vervoerder;private String vertrekSpoor;@XmlElement(name = "RitNummer")public int getRitNummer() {return ritNummer;}public void setRitNummer(int ritNummer) {this.ritNummer = ritNummer;}
    • 71. Create POJO (3)public class VertrekkendeTrein {private int ritNummer;private String vertrekTijd;private String eindBestemming;private String treinSoort;private String routeTekst;private String vervoerder;private String vertrekSpoor;@XmlElement(name = "RitNummer")public int getRitNummer() {return ritNummer;}public void setRitNummer(int ritNummer) {this.ritNummer = ritNummer;}<RitNummer><VertrekTijd><EindBestemming><TreinSoort><RouteTekst><Vervoerder><VertrekSpoor>
    • 72. Create POJO (3)public class VertrekkendeTrein {private int ritNummer;private String vertrekTijd;private String eindBestemming;private String treinSoort;private String routeTekst;private String vervoerder;private String vertrekSpoor;@XmlElement(name = "RitNummer")public int getRitNummer() {return ritNummer;}public void setRitNummer(int ritNummer) {this.ritNummer = ritNummer;}<RitNummer><VertrekTijd><EindBestemming><TreinSoort><RouteTekst><Vervoerder><VertrekSpoor>
    • 73. Parse String to POJOOutput = response.getEntity(String.class);Unmarshaller jaxbUnmarshaller =jaxbContext.createUnmarshaller();StringReader reader = new StringReader(output);ActueleVertrekTijden actueleVertrekTijden =(ActueleVertrekTijden) jaxbUnmarshaller.unmarshal(reader);System.out.println(actueleVertrekTijden.getVertrekkendeTrein().get(1).getEindBestemming());
    • 74. Parse String to POJOOutput = response.getEntity(String.class);Unmarshaller jaxbUnmarshaller =jaxbContext.createUnmarshaller();StringReader reader = new StringReader(output);ActueleVertrekTijden actueleVertrekTijden =(ActueleVertrekTijden) jaxbUnmarshaller.unmarshal(reader);System.out.println(actueleVertrekTijden.getVertrekkendeTrein().get(1).getEindBestemming());
    • 75. Parse String to POJOOutput = response.getEntity(String.class);Unmarshaller jaxbUnmarshaller =jaxbContext.createUnmarshaller();StringReader reader = new StringReader(output);ActueleVertrekTijden actueleVertrekTijden =(ActueleVertrekTijden) jaxbUnmarshaller.unmarshal(reader);System.out.println(actueleVertrekTijden.getVertrekkendeTrein().get(1).getEindBestemming());
    • 76. Parse String to POJOOutput = response.getEntity(String.class);Unmarshaller jaxbUnmarshaller =jaxbContext.createUnmarshaller();StringReader reader = new StringReader(output);ActueleVertrekTijden actueleVertrekTijden =(ActueleVertrekTijden) jaxbUnmarshaller.unmarshal(reader);System.out.println(actueleVertrekTijden.getVertrekkendeTrein().get(1).getEindBestemming());
    • 77. Handle Errors<error><message>No station found for input ecvve</message></error>if(xml.contains("error")){// parse to error object} else if(xml.contains("name")){// parse to different object}
    • 78. ConclusionIf you want something that is:– Easy to maintain– FlexibleUse a programming language for your automatedtesting.
    • 79. Questions
    • 80. Thank you!Source available on GitHub:https://github.com/roydekleijn/webservicetestsBook: https://leanpub.com/LearningSelenium/Twitter: https://twitter.com/TheWebTesterLinkedIn: http://www.linkedin.com/in/roydekleijnWebsite: http://rdekleijn.nlGet your FREE copy usingcoupon code: TADNL2013(coupon code valid for 2 months)

    ×