> ## Content Index
> Fetch the complete content index at: https://www.workroom-productions.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Exercise: jq for testers
- URL: https://www.workroom-productions.com/exercise-jq-for-testers/
- Published: 2025-10-14T23:02:04.000Z
- Updated: 2025-10-16T13:59:10.000Z
- Description: Testing-related exercises for `jq`
- Author: James Lyndsay
- Tags: Exercises

A set of testing-relevant exercises to help testers use, and see the use of, `jq` – a tool to filter and manipulate json.

#### Notes on `jq`

**(maybe on a page)*

JSON is a text-based record format as a hierarchy – it's not rows and columns. A JSON record is typically an object `{}` or a list `[]`, and everything inside is a `key: value` – and those values can themselves be objects `{}` (named parts in any order) or lists `[]` (ordered rows), giving the hierarchy. The basic unit is `key : value` , one per line.

`jq` lets you filter based on name (`.foo` shows you a top level value thta has the key `foo`), lets you drill down in to a hierarchy (`.foo.bar` shows you the value for the property `bar` under `foo`), and lets you iterate or access specifics in a list with `[` *`n`*`]` (`.[].foo` will, if you've given `jq` a list, give you the value of the property `foo` on every item on the list, while `.[0].foo` will give you the first.

`jq` stacks commands – you'll send information from left to right with `|`, and you'll often send to one of `jq`'s collection commands e.g. `.[].foo | unique | sort`, or to a selection command `.foo[] | select(.bar == "moon")`

Ultimately, it's a powerful filtering language for extracting, exploring and creating data. I'll not be rewriting the [manual](https://jqlang.github.io/jq/manual/), and the [cookbook](https://github.com/jqlang/jq/wiki/Cookbook) shows the complex tasks the tool can manage. 

  
****Reading a query:** 

- if you see a `jq` with information in all the `[]`, it’s like dot notation – it’s effectively an address.
- If a `[]` is empty, it’s iterating, and if you see a `|` it’s filtering or aggregating, sometimes to another filter, sometimes to a keyword like `sort` or `select(` .
- If you see a `..` it’s traversing the whole tree, and a `?` means it’s finding stuff, or checking stuff and handling errors.
- If you see `.` then that’s picking out everything, and `.foo` picks out the thing called `foo` at whatever level the `jq` reader is at. `,` separates and aggregates queries.
- If there’s a `[` and `]` around something that produces information, then that information is being wrapped up as an array. If it’s wrapped in `{` and `}` you’re getting an object.
  
For the exercises, we'll use online `jq` tools. As with regex, I reckon that we don't need to be expert with `jq`, if we have tools to help build and explore queries. All the following tools take in json and a query, and show you the results in real time.

- [JQ / Playground](https://jq.port.io) is a page that lets you ask for `jq` queries in plain language, and to see their effects in real time.
- [JQ Play Offline](https://jiehong.gitlab.io/jq%5Foffline/?query=.) is a page that shows you the results of queries more readably, and lets you work with command-line options
- [The JQ Playground](https://play.jqlang.org) lets you get your json from an http endpoint – and is from the makers of `jq`. It runs slightly less swiftly.

`jq` is primarily a command line tool: These pages are handy for building or testing a query, and for learning through playing, but you'll want the command line version to do work. The tools abstract away the command-line syntax, which goes `jq -c '.fruit.color,.fruit.price' fruit.json` – wrapping the command in `''`, acting on a file, and giving an option.

However, `jq` is not always available, because it's not one of the core xNIX toolset. Its official page is [jqlang.org](https://jqlang.org), and 

## Exercise 1 – exploring data with `jq`

*10 minutes*

We'll use the data below, which is a generated JSON output from an imaginary system that logs events to an `events` object, and logs traces to a `traces` object.

- use `keys` to show the top-level keys
- use `traces[]` to show everything in the traces array
- use `.traces[].traceId` to show the traceIDs.  
  - Aside: Compare with `.traces[] .traceId` and `.traces[] | traceId`
  - Aside: Compare with `.traces | map(.traceId) | unique` and  
  `[ .traces[] | .traceId ] | unique`
- use `events[]` to show everything in the events array
- use `events[0]` to show the first event in the events array
- use `.events | map(.traceId) | unique` to show all the unique traceIDs in the events array.
- use `.traces | map({(.traceId): [.spans[].name]}) | add` to show all event names for each trace.
- use `.events[] | select(.type == "mobile_request") | .data.device` to see all devices for mobile requests.

This will, I hope, let you be familiar with accessing by name, with iterating and picking – and familiar with the data itself.

## Exercise 2 – building queries

*10 mins*

Imagine something you'd like to know as a tester from this data. Use an LLM of your choice, or [JQ / Playground](https://jq.port.io) above, to find a query. Try it out. Parse the query you got.

Share with the rest of the group – they may try it out, parse it themselves, check that the data is right, or see if they can get the same data in a different way.

## Exercise 3 – Generating data with `jq`

Wrap a `jq` command in `[]` or `{}` to generate an array or object. 

### Sample Data

```json
{
  "traces": [
    {
      "traceId": "123456789",
      "duration": 2000,
      "spans": [
        {
          "id": "span1",
          "name": "web_request",
          "startTime": 1634491200000,
          "endTime": 1634491201000,
          "tags": {
            "http.method": "GET",
            "http.url": "/api/users"
          }
        },
        {
          "id": "span2",
          "name": "database_query",
          "startTime": 1634491201000,
          "endTime": 1634491201500,
          "tags": {
            "db.query": "SELECT * FROM users WHERE id = 1"
          }
        },
        {
          "id": "span3",
          "name": "cache_lookup",
          "startTime": 1634491201500,
          "endTime": 1634491201800,
          "tags": {
            "cache.key": "user_profile_1"
          }
        }
      ]
    },
    {
      "traceId": "987654321",
      "duration": 3000,
      "spans": [
        {
          "id": "span1",
          "name": "web_request",
          "startTime": 1634491202000,
          "endTime": 1634491203000,
          "tags": {
            "http.method": "POST",
            "http.url": "/api/payments"
          }
        },
        {
          "id": "span2",
          "name": "payment_processing",
          "startTime": 1634491203000,
          "endTime": 1634491204000,
          "tags": {
            "payment.amount": 100.00,
            "payment.method": "credit_card"
          }
        },
        {
          "id": "span3",
          "name": "fraud_check",
          "startTime": 1634491204000,
          "endTime": 1634491204500,
          "tags": {
            "fraud.score": 10
          }
        }
      ]
    },
    {
      "traceId": "456789123",
      "duration": 1500,
      "spans": [
        {
          "id": "span1",
          "name": "mobile_request",
          "startTime": 1634491205000,
          "endTime": 1634491205500,
          "tags": {
            "http.method": "GET",
            "http.url": "/api/products"
          }
        },
        {
          "id": "span2",
          "name": "product_catalog_lookup",
          "startTime": 1634491205500,
          "endTime": 1634491206000,
          "tags": {
            "product.category": "electronics"
          }
        }
      ]
    },
    {
      "traceId": "321654987",
      "duration": 2500,
      "spans": [
        {
          "id": "span1",
          "name": "web_request",
          "startTime": 1634491207000,
          "endTime": 1634491208000,
          "tags": {
            "http.method": "POST",
            "http.url": "/api/orders"
          }
        },
        {
          "id": "span2",
          "name": "inventory_check",
          "startTime": 1634491208000,
          "endTime": 1634491208500,
          "tags": {
            "product.id": "prod123",
            "quantity": 5
          }
        },
        {
          "id": "span3",
          "name": "order_processing",
          "startTime": 1634491208500,
          "endTime": 1634491209500,
          "tags": {
            "order.id": "order456",
            "order.total": 50.00
          }
        }
      ]
    },
    {
      "traceId": "159753",
      "duration": 1000,
      "spans": [
        {
          "id": "span1",
          "name": "mobile_request",
          "startTime": 1634491210000,
          "endTime": 1634491210500,
          "tags": {
            "http.method": "GET",
            "http.url": "/api/notifications"
          }
        },
        {
          "id": "span2",
          "name": "notification_fetch",
          "startTime": 1634491210500,
          "endTime": 1634491211000,
          "tags": {
            "notification.type": "promotion",
            "notification.message": "25% off sale!"
          }
        }
      ]
    },
    {
      "traceId": "753159",
      "duration": 1800,
      "spans": [
        {
          "id": "span1",
          "name": "web_request",
          "startTime": 1634491212000,
          "endTime": 1634491212500,
          "tags": {
            "http.method": "GET",
            "http.url": "/api/profile"
          }
        },
        {
          "id": "span2",
          "name": "user_profile_fetch",
          "startTime": 1634491212500,
          "endTime": 1634491213000,
          "tags": {
            "user.id": "user123",
            "user.email": "user@example.com"
          }
        },
        {
          "id": "span3",
          "name": "settings_fetch",
          "startTime": 1634491213000,
          "endTime": 1634491213800,
          "tags": {
            "settings.theme": "dark",
            "settings.language": "en"
          }
        }
      ]
    },
    {
      "traceId": "951357",
      "duration": 2200,
      "spans": [
        {
          "id": "span1",
          "name": "mobile_request",
          "startTime": 1634491215000,
          "endTime": 1634491215500,
          "tags": {
            "http.method": "POST",
            "http.url": "/api/feedback"
          }
        },
        {
          "id": "span2",
          "name": "feedback_submit",
          "startTime": 1634491215500,
          "endTime": 1634491216000,
          "tags": {
            "feedback.rating": 4,
            "feedback.comment": "Great app, but could use more features."
          }
        },
        {
          "id": "span3",
          "name": "support_ticket_create",
          "startTime": 1634491216000,
          "endTime": 1634491217200,
          "tags": {
            "ticket.id": "ticket123",
            "ticket.priority": "medium"
          }
        }
      ]
    },
    {
      "traceId": "357951",
      "duration": 1700,
      "spans": [
        {
          "id": "span1",
          "name": "web_request",
          "startTime": 1634491218000,
          "endTime": 1634491218500,
          "tags": {
            "http.method": "GET",
            "http.url": "/api/analytics"
          }
        },
        {
          "id": "span2",
          "name": "data_aggregation",
          "startTime": 1634491218500,
          "endTime": 1634491219000,
          "tags": {
            "data.source": "user_activity",
            "data.timeframe": "last_7_days"
          }
        },
        {
          "id": "span3",
          "name": "report_generation",
          "startTime": 1634491219000,
          "endTime": 1634491219700,
          "tags": {
            "report.id": "weekly_analytics",
            "report.format": "pdf"
          }
        }
      ]
    },
    {
      "traceId": "753951",
      "duration": 2800,
      "spans": [
        {
          "id": "span1",
          "name": "mobile_request",
          "startTime": 1634491220000,
          "endTime": 1634491220500,
          "tags": {
            "http.method": "PUT",
            "http.url": "/api/settings"
          }
        },
        {
          "id": "span2",
          "name": "user_settings_update",
          "startTime": 1634491220500,
          "endTime": 1634491221000,
          "tags": {
            "setting.language": "es",
            "setting.notification_preferences": "email"
          }
        },
        {
          "id": "span3",
          "name": "email_notification",
          "startTime": 1634491221000,
          "endTime": 1634491222800,
          "tags": {
            "email.recipient": "user@example.com",
            "email.subject": "Your settings have been updated"
          }
        }
      ]
    }
  ],
  "events": [
    {
      "timestamp": 1634491200000,
      "type": "user_login",
      "data": {
        "userId": "user123",
        "ipAddress": "192.168.1.100"
      },
      "traceId": "123456789"
    },
    {
      "timestamp": 1634491201000,
      "type": "database_query",
      "data": {
        "query": "SELECT * FROM users WHERE id = 1"
      },
      "traceId": "123456789"
    },
    {
      "timestamp": 1634491201800,
      "type": "cache_hit",
      "data": {
        "cacheKey": "user_profile_1"
      },
      "traceId": "123456789"
    },
    {
      "timestamp": 1634491202000,
      "type": "payment_initiated",
      "data": {
        "paymentId": "payment123",
        "amount": 100.00
      },
      "traceId": "987654321"
    },
    {
      "timestamp": 1634491204000,
      "type": "fraud_check_complete",
      "data": {
        "fraudScore": 10
      },
      "traceId": "987654321"
    },
    {
      "timestamp": 1634491205000,
      "type": "mobile_request",
      "data": {
        "userId": "user456",
        "device": "iPhone"
      },
      "traceId": "456789123"
    },
    {
      "timestamp": 1634491205500,
      "type": "product_catalog_lookup",
      "data": {
        "productCategory": "electronics"
      },
      "traceId": "456789123"
    },
    {
      "timestamp": 1634491207000,
      "type": "order_placed",
      "data": {
        "orderId": "order456",
        "totalAmount": 50.00
      },
      "traceId": "321654987"
    },
    {
      "timestamp": 1634491208500,
      "type": "inventory_check",
      "data": {
        "productId": "prod123",
        "quantity": 5
      },
      "traceId": "321654987"
    },
    {
      "timestamp": 1634491210000,
      "type": "mobile_request",
      "data": {
        "userId": "user789",
        "device": "Android"
      },
      "traceId": "159753"
    },
    {
      "timestamp": 1634491210500,
      "type": "notification_fetched",
      "data": {
        "notificationType": "promotion",
        "notificationMessage": "25% off sale!"
      },
      "traceId": "159753"
    },
    {
      "timestamp": 1634491212000,
      "type": "user_profile_viewed",
      "data": {
        "userId": "user123",
        "userEmail": "user@example.com"
      },
      "traceId": "753159"
    },
    {
      "timestamp": 1634491213000,
      "type": "user_settings_fetched",
      "data": {
        "theme": "dark",
        "language": "en"
      },
      "traceId": "753159"
    },
    {
      "timestamp": 1634491215000,
      "type": "mobile_request",
      "data": {
        "userId": "user456",
        "device": "Android"
      },
      "traceId": "951357"
    },
    {
      "timestamp": 1634491215500,
      "type": "feedback_submitted",
      "data": {
        "rating": 4,
        "comment": "Great app, but could use more features."
      },
      "traceId": "951357"
    },
    {
      "timestamp": 1634491216000,
      "type": "support_ticket_created",
      "data": {
        "ticketId": "ticket123",
        "priority": "medium"
      },
      "traceId": "951357"
    },
    {
      "timestamp": 1634491218000,
      "type": "web_request",
      "data": {
        "userId": "user789",
        "ipAddress": "192.168.1.101"
      },
      "traceId": "357951"
    },
    {
      "timestamp": 1634491218500,
      "type": "data_aggregation",
      "data": {
        "dataSource": "user_activity",
        "timeframe": "last_7_days"
      },
      "traceId": "357951"
    },
    {
      "timestamp": 1634491219000,
      "type": "report_generated",
      "data": {
        "reportId": "weekly_analytics",
        "reportFormat": "pdf"
      },
      "traceId": "357951"
    },
    {
      "timestamp": 1634491220000,
      "type": "mobile_request",
      "data": {
        "userId": "user123",
        "device": "Android"
      },
      "traceId": "753951"
    },
    {
      "timestamp": 1634491220500,
      "type": "user_settings_updated",
      "data": {
        "language": "es",
        "notificationPreferences": "email"
      },
      "traceId": "753951"
    },
    {
      "timestamp": 1634491221000,
      "type": "email_notification_sent",
      "data": {
        "recipient": "user@example.com",
        "subject": "Your settings have been updated"
      },
      "traceId": "753951"
    }
  ]
}
```

##