performerjOccasional ContributorJoined 8 years ago8 Posts1 LikeLikes received1 SolutionView All Badges
ContributionsMost RecentMost LikesSolutionsRe: Reusable assertions for REST error handling in SoapUI Rao, Please don't take this personally. The SmartBear project is one of multiple things I am working on, and presently I can only get to it in the evenings. Initial reason for not trying your code was I was trying to solve the customer-requested problem of how to validate a JSON response (in this case a custom message which only comes back for non-200 responses) against a customer-defined schema, and you were kind enough to point out the bug I had there. Time permitting, I will reuse the class approach you recommended and move the bulk of the code out of a script assertion into a Groovy library to meet the reuse ... all things which are entirely new for me. Hope to have more feedback soon. I appreciate all your help even if I haven't fully leveraged it all yet. Dave Re: Reusable assertions for REST error handling in SoapUI Rao, Good catch. That code indeed put a tautology in there, and for that matter the "keySet" approach didn't pick up the hierarchical nature of the schema. I have corrected with a longer segment of code, but as you have pointed out, it is still not put in class format and organized for clean reuse. For that part I still have work to do. // Logic for comparing response to JSON schema in Groovy import groovy.json.JsonSlurper // List of nested keys recursive function from stackoverflow.com web site (modified to skip / discard certain keys we're not interested in). List<String> getNestedMapKeysFromSchema(Map map, String keyPrefix = '') { def result = [] map.each { key, value -> if (value instanceof Map) { if (key == 'properties') { result += getNestedMapKeysFromSchema(value,"$keyPrefix")} else { result += getNestedMapKeysFromSchema(value,"$keyPrefix$key.") } } else { if (key == 'type' && keyPrefix.length() > 4) { def newPrefix = keyPrefix.substring(0, keyPrefix.length()-1) // Remove the period if we decide this is a data value being returned. result += "$newPrefix" } else { result += "$keyPrefix$key" } } } result } // List of nested keys recursive function from stackoverflow.com web site. List<String> getNestedMapKeys(Map map, String keyPrefix = '') { def result = [] map.each { key, value -> if (value instanceof Map) { result += getNestedMapKeys(value,"$keyPrefix$key.") } else { result += "$keyPrefix$key" } } result } // Mainline code for comparing JSON schema for confirm message with actual confirm message fields received back. def responseStatus = messageExchange.responseHeaders['#status#'][0] def responseStatusCodeValue = responseStatus.substring(9,12) if ( responseStatusCodeValue != '200' ) { // Error code, make sure we got the confirmation message. URL schemaUrl = new URL("http://developers.adp.com/static/Swagger/confirmmessage-schema.json") // Create URL object in Groovy. String jsonSchemaString = "https://developers.adp.com/static/Swagger/confirmmessage-schema.json".toURL().text def jsonSchemaMap = new JsonSlurper().parseText(jsonSchemaString) // Slurp JSON schema data into a Groovy map. def jsonSchemaMapNestedKeys = getNestedMapKeysFromSchema(jsonSchemaMap) // Get the keys in nested form from the schema. def ResponseMessage = messageExchange.response.responseContent // Fetch the JSON payload from the response message. def jsonResponseMap = new JsonSlurper().parseText(ResponseMessage) // Slurp JSON response data into a Groovy map. def jsonResponseMapNestedKeys = getNestedMapKeys(jsonResponseMap) // Get the keys in nested form from the schema. for (key in jsonResponseMapNestedKeys) { assert jsonSchemaMapNestedKeys.contains(key) } // Confirm response's nested keys are contained in schema. assert jsonResponseMap.confirmMessage.protocolStatusCode.codeValue == responseStatusCodeValue // Confirm error code in JSON payload matches HTTP Status Code returned. } else assert responseStatusCodeValue == '200' // Otherwise, assert we got the normal expected response (HTTP Status Code = 200). Re: Reusable assertions for REST error handling in SoapUI I came up with the following which works at the script assertion level. // Logic for comparing response to JSON schema in Groovy import groovy.json.JsonSlurper def responseStatus = messageExchange.responseHeaders['#status#'][0] if ( responseStatus != 200 ) { // Error code, make sure we got the confirmation message. URL schemaUrl = new URL("https://developers.adp.com/static/Swagger/confirmmessage-schema.json") // Create URL object in Groovy. def jsonSchemaMap = new JsonSlurper().parseText(schemaUrl.text) // Slurp JSON schema data into a Groovy map. def ResponseMessage = messageExchange.response.responseContent // Fetch the JSON payload from the response message. def jsonResponseMap = new JsonSlurper().parseText(ResponseMessage) // Slurp JSON response data into a Groovy map. def schemaKeys = jsonResponseMap.keySet() // Get the list of keys from the JSON schema. def responseKeys = jsonResponseMap.keySet()// Get the list of keys from the JSON response. assert schemaKeys == responseKeys // Assert that the key lists from the JSON schema and the JSON response should match. // This is our indicator that we got a valid confirmation message. } else assert responseStatus == 200 // Otherwise, assert we got the normal expected response (HTTP Status Code = 200). From here I think it is mainly a matter of packaging things with classes, etc. to prepare for reuse from a script library. Re: Reusable assertions for REST error handling in SoapUI Rao, Thanks for all the samples. Is there any way to do something equivalent to the Json Schema Validator assertion in the SoapUI tool, except implement it in (or call it from) Groovy? -- Dave JEwell Reusable assertions for REST error handling in SoapUI I've been asked to come up with a way to provide reusable assertions for validating standard error responses (HTTP Status Codes 400, 403, etc.) so that those who develop other SoapUI TestCases that encounter errors don't have to code the same validations of HTTP status codes and JSON error response payload validation over and over again. Since it does not appear to be possible to call one test case from another across projects, I thought the next best thing would be to be to come up with a shared Groovy script library to do these error validations. Is there a Groovy technique that can be used to invoke the same function that is in the native SoapUI Json Schema Validator Assertion? I imagine something like that can be done using JsonSlurper functionality, but I am not familiar enough with Groovy scripting to code that by myself? Any help would be much appreciated. Thanks in advance. SolvedWhy does testsrunner.sh check X11 display status when in command line mode? I encountered the call stack below when I tried to run a testrunner.sh from the command line in Linux (RHEL 7.3). My question is why testrunner.sh should care about the setting of the $DISPLAY variable when you are running in command line mode and not requesting a UI session anyway? I can circumvent the problem by doing an Xlaunch (activating Xming in the background on my Windows 7 client) or by entering the command unset DISPLAY on the command line, but why should this even be necessary? Dave Jewell Failed to create icon: java.awt.AWTError: Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable. Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11GraphicsEnvironment at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103) at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82) at net.sf.jasperreports.engine.util.JRStyledTextParser.<clinit>(JRStyledTextParser.java:88) at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:182) at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:77) at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:87) at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:57) at net.sf.jasperreports.engine.fill.JRFiller.createFiller(JRFiller.java:142) at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:78) at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:624) at com.eviware.soapui.reporting.engine.jasper.GenerateJasperReport.generateJasperReport(GenerateJasperReport.java:291) at com.eviware.soapui.reporting.engine.jasper.JasperReportEngine$GeneratableJasperReport.generate(JasperReportEngine.java:113) at com.smartbear.ready.cmd.runner.pro.SoapUIProTestCaseRunner.generateReports(SoapUIProTestCaseRunner.java:283) at com.smartbear.ready.cmd.runner.pro.SoapUIProTestCaseRunner.runTestCase(SoapUIProTestCaseRunner.java:239) at com.smartbear.ready.cmd.runner.SoapUITestCaseRunner.runRunner(SoapUITestCaseRunner.java:430) at com.smartbear.ready.cmd.runner.pro.SoapUIProTestCaseRunner.runRunner(SoapUIProTestCaseRunner.java:98) at com.smartbear.ready.cmd.runner.AbstractSoapUIRunner.run(AbstractSoapUIRunner.java:257) at com.smartbear.ready.cmd.runner.AbstractSoapUIRunner.runFromCommandLine(AbstractSoapUIRunner.java:160) at com.smartbear.ready.cmd.runner.pro.SoapUIProTestCaseRunner.init(SoapUIProTestCaseRunner.java:82) at com.smartbear.ready.cmd.runner.pro.SoapUIProTestCaseRunner.main(SoapUIProTestCaseRunner.java:78) Re: Assertion fail for valid HTTP code 204 Ok, just tried the maintenance build and that fixed the problem. Thanks! Re: Assertion fail for valid HTTP code 204 We recently installed Ready! API 1.9.0 and I am finding this behavior of HTTP 204 asserts failing due to a Content Length being specified in the response header. I was looking for a workaround that could be applied at the virt level (e.g. in a response script) that would suppress the sending of the content length. Does anyone else have a workaround for this, either at the virt level or at the assert level?