Logging HTTP Response Headers and Bodies of Web Service --- Materials applied


#1

I have made a demo project and published at

----------

Problem to solve

  1. I want to test a Web Service API, like katalon-studio-samples/jira-api-tests
  2. I want to save HTTP Response Header and Response Body into files in JSON format.
  3. I want to retain files chronologically for logging purpose. I do not like overwriting files. If I execute a single Test Suite 3 times, then I want to retain 3 sets of json files.
  4. I will look back retained sets of json files frequently. So I want a nice GUI that enables me to retrieve stored files quickly.

Solution

I would introduce Materials, a java/groovy library that resolves output file paths in a well-structured format. Thecom.kazurayam.materials.MaterialRepository class provides convenient methods with which I can solve the above-mensioned problems easily.

  1. resolveMaterialPath(String testCaseId, String fileName) method returns java.nio.file.Path object for a File to be created. The path would be in the format of
${projectDir}/Materials/${testSuiteName}/${testSuiteTimestamp}/${testCaseName}/${subdirs}/${fileName}
  1. makeIndex() method generates the ./Materials/index.html file. This is a simple viewer for the Materials folder contents.

How to run the demo

  1. download the zip of this project from releases page.
  2. unzip it. You will obtain a folder named KatalonDiscussion10209.
  3. start your Katalon studio, and open the project
  4. open a Test Suite named Test Suites/TS_Materials_applied and run it.
  5. you should run it multiple times. e.g., try 3 times.

What the test does

This project is based on the katalon-studio-samples/jira-api-tests project. I added a few codes on it without changing files of the original project.

The Test Suites/TS_Materials_applied executes Test Cases/Simple examples/api-2-issue/Get issue/Get an issue by Key - 1 - Materialized. The test case code looks like this:

// Send the request and get the responseresponse = WS.sendRequest(findTestObject('Simple examples/api-2-issue/Get issue/Get an issue by Key'))// Verify the responseWS.verifyResponseStatusCode(response, 200)// make MaterialRepository accessibleMaterialRepository mr = (MaterialRepository)GlobalVariable.MATERIAL_REPOSITORY// store the HTTP Response Headers into filePath path2 = mr.resolveMaterialPath(GlobalVariable.CURRENT_TESTCASE_ID, "headers.json")Map<String, List<String>> headerFields = response.getHeaderFields()String headersJson = CustomKeywords.'com.kazurayam.ksbackyard.WebServiceTestSupport.convertHeaderFieldsToJsonString'(headerFields)path2.toFile().append(headersJson, 'utf-8')// store the HTTP Response Body into filePath path3 = mr.resolveMaterialPath(GlobalVariable.CURRENT_TESTCASE_ID, "body.json")String body = response.getResponseBodyContent()path3.toFile().append(body, 'utf-8')

This test case send a HTTP GET request to a RESTFul URL https://katalon.atlassian.net/rest/api/2/issue/KD-1000?expand=names&fields=summary,status,issuetype,assignee,project,priority,description&= . The test case makes a bit of assertions over the response. And it writes the HTTP Response Headers and Body into files on local disk in JSON format.

output

By running Test Suites/TS_Materials_applied, a new folder <projectDir>/Materials will be created. In there you can find a folder tree and a HTML file named index.html.

Materials_index

You can browse the index.html. It will look like this:

index_html

In the index you will find as many records of test suite runs as you executed. In the above screenshot, you can find 3 times of test suite run recorded.

Each test suite run contains a record of test case run, which contains links to the files created.

By clicking the links, you can view the files in modal widdow. Here is headers.json:

headers_json

Here is body.json:

body_json

Path format

The created files has a path like this:

${projectDir}/Materials/${testSuiteName}/${testSuiteTimestamp}/${testCaseName}/${subdirs}/${fileName}

A concrete path example:

./Materials/TS_Materials_applied/20181018_140249/Simple examples.api-2-issue.Get issue.Get an issue by Key - 1 - Materialized/header.json

Please note that this folder tree contains a timestamp layer yyyyMMdd_hhmmss. Having a timestamp layer enables you to retain outputs as long as you like until you intensionally delete them. This chronological folder structure is best fit for logging purpose.

How to reproduce a Materials-enabled project for your self

Here I would describe, step by step, for you how to recreate a Katalon Studio project which has the Materials library builting and enabled.

  1. create a new katalon project, or clone some existing project. For example, clone the katalon-studio-samples/jira-api-testsproject.
  2. import Materials-0.22.0.jar or heigher into your katalon project. Refer to the Katalon documentation 'Import Java library’for operation instruction. You can download jar from release page. Or you can reuse the jar already imported into this project. ExternalLibraies
  3. Edit Profiles > default in your project. Add MATERIALS_REPOSITORY with type Null. Add CURRENT_TESTCASE_ID with type String. Profiles_default
  4. Create a Test Listener in your project, and copy & paste the source of Tests. You need not change it at all. If you have your own test listener, then carefully edit it so that your test listener works similar to the Tests.
  5. Add a test case named Test Cases/cleanMaterials in your project. Copy and paste the source of Test Cases/clearMaterials. You need not to change the code at all.
  6. Add a test case name Test Cases/makeIndex in your project. Copy and paste the source of Test Cases/makeIndex. You need not to change the code at all.
  7. Now you add your own test case which actually test your target Web Services. Refer to Test Cases/Simple examples/api-2-issue/Get issue/Get an issue by Key - 1 - Materialized as an example.
  8. Add a test suite which calls 3 test cases — cleanMaterials, your own test case and makeIndex. TestSuite. The test suite can have any name you like.
  9. In the definiton of test suite, there is a row labeled Run. In the Run row, there are toggle controls. You can choose each test cases to run or not. If you toggle on the cleanMaterials test case, then the ./Materials directory will be cleaned every time when the test suite runs. If you toggle off, then you can see multiple records of test sute runs accumulated in the index.html viewer.

#2

This technique was available in Katalon Studio 5.7.1 and lower.

However, in 5.8.0 and higher, this technique became difficult due to the following restriction:

Guys, please vote for the bug report.


#3

kazurayam

From: https://docs.katalon.com/katalon-studio/new/version-584.html

Improvements

  • Allow duplicating test cases in the same test suite

  • Correct generated verification code for XML responses

  • Add NULL type back to Variable Type list

have fun!


#4

Great Blog! I have a question,I want simply to log SOAP message details and the transport protocol request/response (header) along with it. I took help from https://avastsupportnumber.co.uk/blog/fix-avast-blocking-league-legends/ but didn’t resolve my issues.


#5

tech support,

I have a question,I want simply to log SOAP message details and the transport protocol request/response (header) along with it.

What do you want me to do?

If you want me to make a Katalon Studio project as example of logging SOAP interaction, then please provide your code as starter. I need your Test Object which wraps URL of the Web Service in question, and a Test Case which performs WS.sendRequest(TestObject).

-----

https://avastsupportnumber.co.uk/blog/fix-avast-blocking-league-legends/ ----- I do not understand this site at all.


#6

Hey @kazurayam Thanks for sharing this code with us. I am getting one issue while implementing the same in my project.
2019-07-11 12:12:13.589 ERROR c.k.katalon.core.main.TestCaseExecutor - :x: Test Cases/Achecker/makeIndex FAILED.
Reason:
groovy.lang.MissingMethodException: No signature of method: com.kazurayam.materials.impl.MaterialRepositoryImpl.makeIndex() is applicable for argument types: () values: []
at makeIndex.run(makeIndex:14)

steps mentioned in https://github.com/kazurayam/KatalonDiscussion10209/blob/master/Scripts/makeIndex/Script1539827017814.groovy is not getting resolved to makeIndex(). I tried removing imports as well but no luck. Any changes?


#7

In the Drivers folder, what version of Materials-x.x.x.jar do you have? Is it 0.22.0?

Please share your “Test Cases/Achecker/makeIndex” script.


#8

Version is 0.71, I see I downloaded from https://github.com/kazurayam/Materials/releases but in github project its 0.22? Which one to use?

makeIndex script
import com.kazurayam.materials.MaterialRepository

import internal.GlobalVariable as GlobalVariable

/**

  • makeIndex

  • compiles a HTML at ./Materials/index.html

*/

// prepare instance of MaterialRepository

MaterialRepository mr = (MaterialRepository)GlobalVariable.MATERIAL_REPOSITORY

assert mr != null

// make ./Material/index.html file

mr.makeIndex()


#9

This line expects that you have a Test Listener script like this: https://github.com/kazurayam/KatalonDiscussion10209/blob/master/Test%20Listeners/Tests.groovy

Do you have such Test Listener script?


#10

Yes its in place.


#11

Use Materials-0.70.8

This should work for you without code change for you.


#12

Thanks @kazurayam, with library change its working fine.
One help I need it. The https response which I am getting is in html format. So i made a change in your test case code and saving it as html report.
// store the HTTP Response Body into file

Path path3 = mr.resolveMaterialPath(GlobalVariable.CURRENT_TESTCASE_ID, “report.html”)

String body = response.getResponseBodyContent()

path3.toFile().append(body, ‘utf-8’)

But getting error in index.html as
this.getFileType()=’{“FileType”:{“extension”:"",“mimeTypes”:[""]}}’ is unexpected

Can you suggest what needs to be done?


#13

In fact, MaterialRepository#makeIndex() method was removed at v0.71.0. ---- well, backward-compatibility corrupted.

The most up-to-date makeIndex script is like this:

Until the version 0.70.8, the “Materials” directory is always located immediately under in the project directory. You could not move the “Materials” directory to somewhere you want to (for example NFS for Widows Netword-drive moutend directory). This was incovenient for me.

At the version 0.71.0 , I changed the Materials API significantly in order to enable locating “Materials” directory at anywhere you want. This change was too fundamental so that I had to break the backward compatibility. Hense the “makeIndex” script need to be significantly different form the previous one.


#14

Katalon Studio naively expects that Web Service response IS in the format of JSON or XML.
Katalon Studio seems to be buggy to process a response in plain text or HTML format.

Surprised?

I was surprised when I found that fact one day.

Especially getResponseBodyContent() method.


#15

This message implies that your HTTP Server responding a HTTP response without HTTP “Content-Type” header, or “Content-Type” header is there with empty string value.

Please see the
getResponseBodyContent()
implementation of ResponseObject as I mentioned above. That code is dependent how the Content-Type is given.

To me, your target Web App is pretty immature — buggy yet. You should check HTTP Response header first with Chrome browser or Wireshark before trying to process with Katalon Studio.


#16

Ok thanks for the information


#17

Yeah I just saw that there is an issue with data binding which running the suite. I am working on passing a variable from suite to web service using data binding.


#18

Transfer-Encoding: chunked
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=0; max-age=0;
Server: nginx
Connection: keep-alive
Set-Cookie: CheckerID=3b7ufjuk7vapr61quco73vkqi7; path=/
Date: Thu, 11 Jul 2019 10:10:43 GMT
Content-Type: text/html

Also response is something like this below

<?xml version="1.0" encoding="ISO-8859-1"?> ul { font-family: Arial; margin-bottom: 0px; margin-top: 0px; margin-right: 0px; } li.msg_err, li.msg_info { font-family: Arial; margin-bottom: 20px; list-style: none; } span.msg{ font-family: Arial; line-height: 150%; } code.input { margin-bottom: 2ex; background-color: #F8F8F8; line-height: 130%; } span.err_type{ padding: .1em .5em; font-size: smaller; }

Result: CONDITIONAL PASS    593 Potential Problems  


#19

The response you got looks very strange. Your Application Under Test seems to be buggy yet.


#20

I have just released Materials-0.71.4.jar

In this version, com.kazurayam.materials.MaterialRepository#makeIndex() method is restored and available just as it was in the version 0.70.8 and older.