Structured Functional Automated Web Service Testing

2,293 views

Published on

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
2,293
On SlideShare
0
From Embeds
0
Number of Embeds
1,536
Actions
Shares
0
Downloads
0
Comments
0
Likes
2
Embeds 0
No embeds

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.
  • Structured Functional Automated Web Service Testing

    1. 1. Structured Functional Automated WebService TestingRoy de Kleijn
    2. 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. 3. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    4. 4. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    5. 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. 6. Architecture - conventionalapplicationDB
    7. 7. Web Service Based Architecture• Scalable
    8. 8. Web Service Based Architecture• Scalable• Support for any application type
    9. 9. Web Service Based Architecture• Scalable• Support for any application type• Language independent
    10. 10. Web Service Based Architecture• Scalable• Support for any application type• Language independent• Central business logic
    11. 11. Web Service Based Architecture• Scalable• Support for any application type• Language independent• Central business logic• Standardised integration
    12. 12. Different types• Protocols: WSDL / SOAP / REST
    13. 13. Different types• Protocols: WSDL / SOAP / REST• REST (Representational State Transfer)– Defined by HTTP interface
    14. 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. 15. Architecture - SOAapplication
    16. 16. Architecture - SOAapplication DBService1Service2Service3
    17. 17. Architecture - SOADesktopapplicationMobileapplicationThird-partyapplication
    18. 18. Architecture - SOADesktopapplicationMobileapplicationThird-partyapplicationDBService1Service2Service3Service4Third-party
    19. 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. 20. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    21. 21. Benefits for a tester• Less brittle tests– No GUI involved, no browser time-outs
    22. 22. Benefits for a tester• Less brittle tests– No GUI involved, no browser time-outs• Testing can start in an early phase
    23. 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. 24. Testing PyramidUISERVICEUNITDevelopers
    25. 25. Testing PyramidUISERVICEUNITAutomated UI TestsAutomated API TestsAutomated Unit TestsDevelopers
    26. 26. Testing PyramidUISERVICEUNITAutomated UI TestsAutomated API TestsAutomated Unit TestsCompoundIsolationDevelopers
    27. 27. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    28. 28. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    29. 29. Circle of Impact – changing coreCoreS1S2S3A1A2A3
    30. 30. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    31. 31. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    32. 32. Circle of Impact – changing serviceCoreS1S2S3A1A2A3
    33. 33. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    34. 34. Testing a Web Service• Pitfalls• General advice• Tools you can use
    35. 35. Pitfalls• Using performance test tools
    36. 36. Pitfalls• Using performance test tools– Hard to use pre/post conditions
    37. 37. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts
    38. 38. Pitfalls• Using performance test tools– Hard to use pre/post conditions– Hard to create maintainable scripts– Hard to combine testtypes
    39. 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. 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. 41. General advice• Use a programming language
    42. 42. General advice• Use a programming language– IDE features• Auto-completion, refactoring
    43. 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. 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. 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. 46. Tools you can use• Jersey– Making REST requests• Jackson– JSON processor• JAXB– XML processor• JsonPath– Extract parts of a JSON document
    47. 47. Tools you can use• TestNG– Java testing framework• XMLUnit– Assertions for XML, validate against XSD schema• Hamcrest– General matcher library
    48. 48. Agenda1. Web Service introduction2. Whats in it for testers ?3. Testing a Web Service4. Cases
    49. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 60. Case 2Imagine you have to control a relatively difficult XML-string.
    61. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 78. ConclusionIf you want something that is:– Easy to maintain– FlexibleUse a programming language for your automatedtesting.
    79. 79. Questions
    80. 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)

    ×