SEAMful: Service

Beyond basic automation, you will need to send requests as a part of the same session so that cookie management is done automatically for you.

Along with this you also get other benefits in the form of common settings across all requests that are sent as a part of this session.

Arjuna’s HttpService class offers this style of automation in an approachable and comprehensive manner.

Creating an HTTP Service

Anonymous Service

You can create a new service using Http.service method to create an object of HttpSerive.

Following is an example of the most basic construct for creating an HttpService:

svc = Http.service(url="https://svc.com/api")

The url argument sets the base/default URL for this HttpService. If relative path is used as a route in sender methods like get(), then this URL is prefixed to their provided routes.

Named Service

You can also create a named service, which is critical if you are planning to do more involved implementations for SEAMful Model for HTTP Layer Automation (In-Progress).

Following is an example of the most basic construct for creating a named HttpService:

svc = Http.service(name="myservice", url="https://svc.com/api")

A named service must have a corresponding directory with the same name in <Project Root>/httpauto/service directory. For example

myproj
  - httpauto
    - service
      - myservice

All the sections that follow are applicable for anonymous as well as named services.

Supported HTTP Methods in Arjuna

Currently the following HTTP methods/verbs are supported:

Basic GET Example

Simulating a request with a given HTTP method is achieved by making correspindingly named methods in Http object.

Following is an example of a basic GET request:

svc = Http.service(url="https://svc.com/api")

# Using absolute routes in requests
svc.get("https://svc.com/api/res/someid1")
svc.get("https://svc.com/api/res/someid2")

# With relative route. Base/Default URL of Session is prefixed.
svc.delete("/res/someid1") # Same as https://svc.com/api/res/someid1
svc.delete("/res/someid2") # Same as https://svc.com/api/res/someid2

HTTP Response

All types of requests return an HttpResponse object, which can be inquired to validate or extract data.

Customizing HTTP Requests

You can add request headers, add OAuth bearer token, set default content handler and so on. Explore the HttpService class documentation.

Customizing HTTP Requests

You can customize various parts of the HTTP requests using easy to use constructs as described in the following sections.

Handling Content Types in POST/PUT/PATCH Requests

Purpose

POST/PUT/PATCH HTTP requests have content/body as a part of the HTTP packet which is sent.

This content is ultimately sent as plain text. So, Arjuna converts the content object to text before sending it to the HTTP server.

URL-Encoding as Default Content Type

By default Arjuna takes a dictionary (or other dictionary-like objects) as a content and uses URL-Encoding to convert it to text.

# Content sent as URL encoded
svc.post("http://abc.com/res", content={'a' : 1, 'b': 2})
svc.put("http://abc.com/res", content={'a' : 1, 'b': 2})

For example, in the above code, the provided dictionary is converted to the following:

a=1&b=2

In addition, the Content-Type header is set to application/x-www-form-urlencoded.

Specifying Content-Handlers

Http class provides various content specifiers. You can use any of the following:

Following is a simple example of sending JSON content:

# Content sent as serialized JSON
svc.post("http://abc.com/res", content=Http.content.json({'a' : 1, 'b': 2}))

In the above example, the content will be sent as following:

{"a" : 1, "b": 2}

In addition, the Content-Type header is set to application/json.

Using HttpService’s request_content_handler Global Handler

Arjuna’s HttpService object makes content handling very straight-forward as you will mostly likely use the same content handling type across multiple requests.

You can set the content handler in one go across all the requests that are sent by a given session.

svc = Http.service(url="http://abc.com", request_content_handler=Http.content.json)
svc.post("/res1", content={'a' : 1, 'b': 2})
svc.post("/res2", content={'c' : 1, 'd': 2})
svc.post("/res3", content={'e' : 1, 'f': 2})

Setting a Request Label

All service request methods accept a label argument. This is used in reports and logging to give a user-defined representation of an HTTP request.

Following are basic examples of these calls:

svc.get("/api/res/someid", label="Authorization Request")

Setting Arbitrary Query String Parmaters in URL

A common need in HTTP automation is to set the query parameters in the URL.

One can ofcourse do it with Python string formatting. However, Arjuna makes it easier fpr url-encoded params, the most commonly used format.

You can achieve this for all types of service requests. Following is a get example, where arbitrary key-value arguments are passed to become query parameters:

svc.get("https://app.com/somepath", a=1, something="test")

In the above example, the URL will be

https://another.com/somepath?a=1&something=test

Sometimes, the names in query string are not valid Python names and hence can not be passed as keyword arguments. You can use quer_params argument in such situations.

svc.get("https://app.com/somepath", query_params={'nonpy-name':1, 'something':"test"})

If used in combinations, the keyword arugments will override the values in query_params

svc.get("https://app.com/somepath", query_params={'a':1, 'something':"test"}, a=2)

In the above case, the value of a will be 2:

https://another.com/somepath?a=2&something=test

Analyzing HTTP Response

Test automation code is not just about interactions with HTTP server. You will typicallly place various checks on what it responds with for a given request.

Arjuna provides various easy to use features for this purpose.

Checking Expected HTTP Status Code(s)

Inquiring

Status code can be easily inquired:

response = svc.get("/obj/someid")
print(response.status_code)

Asserting

You can also assert status codes by inquiring HttpResponse object as follows:

response = svc.get("/obj/someid")
response.assert_status_codes(200, msg="Your context string")
response.assert_status_codes({200, 404}, msg="Your context string")

xcodes Argument

You can set a session request to raise an HttpUnexpectedStatusCode exception if expected status code is not got:

svc.get("/obj/someid", xcodes=200)

xcodes Argument in strict Mode

You can set a session request to raise an AssertionError exception if expected status code is not got:

svc.get("/obj/someid", xcodes=200, strict=True)

The HttpResponse Object

If a session request is successful it returns an HttpResponse object.

It provides you with various properties to assert or extract data.

Basic Data Extraction

You can easily extract the following data using response properties:

#Response headers
response.headers

# Status Code
response.status_code

# Status Message
response.status

# Request Information
# In case of redirects, this is for the last request
response.request
response.url
response.query_params

Redirections

An HttpResponse object maintains all redirect history.

You can get a sequence of all redirect HttpResponse objects using redir_history property.

You can get the last redirect response using last_redir_response property.

Handling Response Content

You can get formatted as well as un-formatted response content using following properties:
  • text: Unformatted content as plain text

  • html: Response as an HtmlNode object.

  • json: Response as a JsonDict or JsonList object.

Check Parsing JSON, XML, HTML Files and Strings section in documentation to know more about how to parse and extract data from these content type.