cancel
Showing results for 
Search instead for 
Did you mean: 

[TechCorner Challenge #7] Change an XPath Match assertion to a JSONPath Match assertion

SOLVED
Highlighted
Community Manager

[TechCorner Challenge #7] Change an XPath Match assertion to a JSONPath Match assertion

Imagine that the logic of the server has been changed and you started getting responses from the server in the JSON format instead of XML. And, it may appear that XMLPath assertions don’t suit you anymore. In this case, you need to convert all XPath Match assertions to JSONPath Match assertions in your project. There could be a lot of test steps to change, so it’s better to automate this process.

Task: Create a script to convert XPath Match assertion to JSONPath Match assertion for the REST test steps where the request URL is the following: https://example.com/test.

DifficultyStar_Gold.pngStar_Gold.pngStar_Gold.png

A script should do this:

1. Add the JSONPath Match assertion to REST test steps that have the https://example.com/test endpoint.
2. Convert the XPath expression and expected result from the XPath Match assertion to the JSONPath expression and expected result for the corresponding test steps.
3. Remove the XPath Match assertions for those test steps.

A sample response:

 

JSON

XML

{
	"id": 1111,
	"category": {
		"id": 0,
		"name": "string"
	},
	"name": "doggie",
	"photoUrls": [
		"string"
	],
	"tags": [
		{
			"id": 99,
			"name": "string"
		}
	],
	"status": "available"
}
<Response xmlns="https://petstore.swagger.io/v2/pet">
   <id>1111</id>
   <category>
      <id>0</id>
      <name>string</name>
   </category>
   <name>doggie</name>
   <photoUrls>
      <e>string</e>
   </photoUrls>
   <tags>
      <e>
         <id>99</id>
         <name>string</name>
      </e>
   </tags>
   <status>available</status>
</Response>

 

XMLPath Match assertions example:

 

59754507-858b-4665-b54f-caf98d2443c6.png

 

Condition:

declare namespace ns1='https://petstore.swagger.io/v2/pet';
//ns1:Response[1]/ns1:tags[1]/ns1:e[1]/ns1:id[1]

Expected result:

${#TestCase#ID}

 

Tips:

 

Good luck and have fun😊


Sonya Mihaljova
Community and Education Specialist

Did my reply answer your question? Give Kudos or Accept it as a Solution to help others. ⬇️⬇️⬇️
Tags (1)
1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Community Hero

Change an XPath Match assertion to a JSONPath Match assertion

Task: Create a script to convert XPath Match assertion to JSONPath Match assertion for the REST test steps where the request URL is the following: https://example.com/test.

 

This is a solution created for [TechCorner Challenge #7]

 

Thanks, @sonya_m! When I started as a tester, I realized the power groovy gave for automating even a lot of the manual processes of building tests within ReadyAPI. Having a degree on software engineering, I leaned hard on that and groovy and the api's of ReadyAPI itself to try to remove a lot of the menial parts of building a suite of tests. I love groovy and how much it helps!

 

That being said, I may have went down the more complicated path of looking at the xpath statement and I may have tried to solve a problem that wasn't there. The issue I ran into was the <e> element under tags, as that made me think that may be a listable element. While the example provided only one <e>, I went down the path of how I would write this if there were MORE than that. That's when things (to me) got really complex and hard to follow. I did come up with something, but I am not 100% comfortable with it. I either made it way too complex or made too many (potentially bad) assumptions.

 

Here's what I came up with:

 

 

 

 

 

 

 

def project = context.testCase.testSuite.project;
def URL = "https://example.com/test";


for (ts in project.getTestSuiteList())
{
	for (tc in ts.getTestCaseList())
	{
		for (step in tc.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep))
		{
			
			// Was also stuck here. Is there an easier way to get the rest URL/URI of a REST test step? This method requires the REST step has been ran.
			// Seems like room for improvement. 
			if (step.getHttpRequest().getResponse().getURL().toString().equals(URL))
			{
				for (assertion in step.getAssertionList())
				{
					if (assertion.getName().equals("XPath Match"))
					{
						def xpaths = assertion.getPath().toString().tokenize("\n");						
						def json = xpaths[1]

						// Strip the xpath response statement down to the necessary parts. This makes assumptions on the xpath string always matching the example other than indexed location of E. 
						json = json.replace("//ns1:Response[1]/", "").replaceAll("ns1:", "").replace("tags[1]", "tags").replace("id[1]", "id");
						
						// Split the xpath statement into an array for ease of modifying, using the / character as a delimiter
						json = json.tokenize("/");

						// Assuming the xpath statement is always tags/e/id, the second spot in the array is the position of the <e> element we're concerned with. 
						json[1] = (json[1].replaceAll("[A-z\\[\\]]","").toInteger() - 1).toString()

						// Rebuild the json path.
						json = json[0] + "[" + json[1] + "]." + json[2];
						
						log.info(json);
						// def json = "tags[0].id";
						
						// Get the expected content as a string
						def result = assertion.getExpectedContent().toString();
						
						// Remove the offending assertion
						// step.removeAssertion(assertion);

						// Add new JSONPath assertion
						step.addAssertion("JsonPath Match");
						def jsonAssertion = step.getAssertionByName("JsonPath Match");

						// Set the path and the expected content
						jsonAssertion.setPath(json);
						jsonAssertion.setExpectedContent(result);
					}
				}
			}
		}
	}
}

 

 

 

 

 

 




---

Click the Accept as Solution button if my answer has helped, and remember to give kudos where appropriate too!

View solution in original post

Tags (1)
10 REPLIES 10
Highlighted
Community Hero

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

It's not perfect, because I am not sure if I was supposed to actually figure out a way to convert the Xpath Statement from the XPath Match assertion to something the JsonPath could accept and translate. I was thrown off a bit, so I hard coded that part. Eager to see what others came up with!

 

def project = context.testCase.testSuite.project;
def URL = "https://example.com/test";


for (ts in project.getTestSuiteList())
{
	for (tc in ts.getTestCaseList())
	{
		for (step in tc.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep))
		{
			
			// Was also stuck here. Is there an easier way to get the rest URL/URI of a REST test step? This method requires the REST step has been ran.
			// Seems like room for improvement. 
			if (step.getHttpRequest().getResponse().getURL().toString().equals(URL))
			{
				for (assertion in step.getAssertionList())
				{
					if (assertion.getName().equals("XPath Match"))
					{
						def xpaths = assertion.getPath().toString().tokenize("\n");
						log.info(xpaths[1].toString());
						// def xpaths = xpath.;
						// I could not figure out the sorcery to convert the xpath statement to the json statement. Would be interested to see what others come up with.
						// def json = xpaths[1].replace("//ns1:Response[1]", "").replace("[1]","[0]").replace('''/ns1:''', ".");
						def json = "tags[0].id";
						
						// Get the expected content as a string
						def result = assertion.getExpectedContent().toString();
						
						// Remove the offending assertion
						step.removeAssertion(assertion);

						// Add new JSONPath assertion
						step.addAssertion("JsonPath Match");
						def jsonAssertion = step.getAssertionByName("JsonPath Match");

						// Set the path and the expected content
						jsonAssertion.setPath(json);
						jsonAssertion.setExpectedContent(result);
					}
				}
			}
		}
	}
}



---

Click the Accept as Solution button if my answer has helped, and remember to give kudos where appropriate too!
Highlighted
Community Hero

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

@msiadak,

Hey man....i didn't know how to even start this one, but you've given me a cracking start to one solution. I'm positive i wont get anywhere, but at least i can have a crack now ive got a bit of guidance!

Nice one!

Rich
if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the Subject header field of the post to something more descriptive? This will help people when searching for problems. Ta
Highlighted
Community Manager

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

That's a start! Thank you @msiadak , you are really good at scripting!

 

Who will try to develop this idea? Richie, will you try? msiadak provided us with a great basis, but, yes, he is right - the main task is to find a way of converting XPath to JSONPath!

 

@avidCoder @HimanshuTayal @Radford @nmrao ?🙂

 

Or, maybe, msiadak will finish what he started himself!


Sonya Mihaljova
Community and Education Specialist

Did my reply answer your question? Give Kudos or Accept it as a Solution to help others. ⬇️⬇️⬇️
Highlighted
Community Hero

Change an XPath Match assertion to a JSONPath Match assertion

Task: Create a script to convert XPath Match assertion to JSONPath Match assertion for the REST test steps where the request URL is the following: https://example.com/test.

 

This is a solution created for [TechCorner Challenge #7]

 

Thanks, @sonya_m! When I started as a tester, I realized the power groovy gave for automating even a lot of the manual processes of building tests within ReadyAPI. Having a degree on software engineering, I leaned hard on that and groovy and the api's of ReadyAPI itself to try to remove a lot of the menial parts of building a suite of tests. I love groovy and how much it helps!

 

That being said, I may have went down the more complicated path of looking at the xpath statement and I may have tried to solve a problem that wasn't there. The issue I ran into was the <e> element under tags, as that made me think that may be a listable element. While the example provided only one <e>, I went down the path of how I would write this if there were MORE than that. That's when things (to me) got really complex and hard to follow. I did come up with something, but I am not 100% comfortable with it. I either made it way too complex or made too many (potentially bad) assumptions.

 

Here's what I came up with:

 

 

 

 

 

 

 

def project = context.testCase.testSuite.project;
def URL = "https://example.com/test";


for (ts in project.getTestSuiteList())
{
	for (tc in ts.getTestCaseList())
	{
		for (step in tc.getTestStepsOfType(com.eviware.soapui.impl.wsdl.teststeps.RestTestRequestStep))
		{
			
			// Was also stuck here. Is there an easier way to get the rest URL/URI of a REST test step? This method requires the REST step has been ran.
			// Seems like room for improvement. 
			if (step.getHttpRequest().getResponse().getURL().toString().equals(URL))
			{
				for (assertion in step.getAssertionList())
				{
					if (assertion.getName().equals("XPath Match"))
					{
						def xpaths = assertion.getPath().toString().tokenize("\n");						
						def json = xpaths[1]

						// Strip the xpath response statement down to the necessary parts. This makes assumptions on the xpath string always matching the example other than indexed location of E. 
						json = json.replace("//ns1:Response[1]/", "").replaceAll("ns1:", "").replace("tags[1]", "tags").replace("id[1]", "id");
						
						// Split the xpath statement into an array for ease of modifying, using the / character as a delimiter
						json = json.tokenize("/");

						// Assuming the xpath statement is always tags/e/id, the second spot in the array is the position of the <e> element we're concerned with. 
						json[1] = (json[1].replaceAll("[A-z\\[\\]]","").toInteger() - 1).toString()

						// Rebuild the json path.
						json = json[0] + "[" + json[1] + "]." + json[2];
						
						log.info(json);
						// def json = "tags[0].id";
						
						// Get the expected content as a string
						def result = assertion.getExpectedContent().toString();
						
						// Remove the offending assertion
						// step.removeAssertion(assertion);

						// Add new JSONPath assertion
						step.addAssertion("JsonPath Match");
						def jsonAssertion = step.getAssertionByName("JsonPath Match");

						// Set the path and the expected content
						jsonAssertion.setPath(json);
						jsonAssertion.setExpectedContent(result);
					}
				}
			}
		}
	}
}

 

 

 

 

 

 




---

Click the Accept as Solution button if my answer has helped, and remember to give kudos where appropriate too!

View solution in original post

Tags (1)
Highlighted
Community Manager

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

It works great for the given XPath, @msiadak ! Solved!

 

I am wondering if anybody will dare to write code for a more general case, so that it could work for other Xpath structures, as well.

 


Sonya Mihaljova
Community and Education Specialist

Did my reply answer your question? Give Kudos or Accept it as a Solution to help others. ⬇️⬇️⬇️
Highlighted
Community Hero

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

I won't lie, @sonya_m, I'm still trying to figure this out. So if anyone has a solution and can let me stop thinking about this, that'd be much appreciated! 🤣




---

Click the Accept as Solution button if my answer has helped, and remember to give kudos where appropriate too!
Highlighted
Community Hero

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

Hey!

I'm absolutely nowhere with this one.....waaaay too hard for me.

What's the next challenge? I might have a better chance with that!😉

Ta

Rich
if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the Subject header field of the post to something more descriptive? This will help people when searching for problems. Ta
Highlighted
Community Manager

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

@msiadak You can try shifting your thoughts to the next one, mayhaps, this helps😁

 

@richie this one has max difficulty, a tough one indeed!


Sonya Mihaljova
Community and Education Specialist

Did my reply answer your question? Give Kudos or Accept it as a Solution to help others. ⬇️⬇️⬇️
Highlighted
Community Hero

Re: Your Ideas Needed - Change an XPath Match assertion to a JSONPath Match assertion

@sonya_m, I have to ask. Is there a known solution for converting the xpath statement to json??? I still haven't figured it out. 😑




---

Click the Accept as Solution button if my answer has helped, and remember to give kudos where appropriate too!
New Here?
Join us and watch the welcome video:
Announcements
Top Kudoed Authors