Skip to content

NoSQL for QA โ€‹

If you already know SQL, the jump to NoSQL isn't about learning another language: it's about learning which guarantees disappear and what you must validate because of it. I use MongoDB as the example since it's the most widespread document database.

What changes compared to relational โ€‹

Relational (SQL)Document (MongoDB)
Unit of dataRow in a tableJSON document in a collection
SchemaFixed, enforced by the databaseFlexible: each document can have different fields
RelationshipsJOINs between tablesNested documents or references (no classic JOIN)
ConsistencyStrong by defaultDepends on configuration; often eventual

The last two rows are the ones that change a QA's job.

The day-to-day queries โ€‹

Direct equivalences with what you already do in SQL:

In SQLIn MongoDB
SELECT * FROM customers WHERE document = 'โ€ฆ'db.customers.find({ document: 'โ€ฆ' })
SELECT status FROM service_orders WHERE id = โ€ฆdb.service_orders.find({ _id: โ€ฆ }, { status: 1 })
SELECT COUNT(*) โ€ฆdb.service_orders.countDocuments({ status: 'provisioning' })
GROUP BY โ€ฆ HAVING COUNT(*) > 1db.customers.aggregate([{ $group: { _id: '$document', n: { $sum: 1 } } }, { $match: { n: { $gt: 1 } } }])
js
// Was the service order persisted with the expected structure?
db.service_orders.find({ orderId: 'ORD-10442' })

// Duplicate customers that validation should have prevented
db.customers.aggregate([
  { $group: { _id: '$document', n: { $sum: 1 } } },
  { $match: { n: { $gt: 1 } } }
])

What to validate (precisely because there's no schema) โ€‹

  • The implicit schema. The database accepts any document, so a misspelled field (satus instead of status) doesn't fail on write: it fails on read, in another system, weeks later. Verifying the structure of persisted documents is the test's job, not the database's.
  • Missing fields vs. null fields. In Mongo they're different things ({ field: null } exists; a document without the field doesn't). Queries like { field: null } match both โ€” choose assertions deliberately ($exists).
  • Eventual consistency. In distributed architectures, what you just wrote may take time to become visible. An immediate find that doesn't return the document isn't always a bug: validate with active waiting, not with sleep.

The rest of the NoSQL map, one line each โ€‹

  • Key-value (Redis) โ€” caches and sessions; in tests, the usual cause of "I deleted it from the database but I still see it".
  • Columnar (Cassandra) โ€” time series and huge volumes, per-query configurable consistency.
  • Graph (Neo4j) โ€” relationships as the primary data; useful to know they exist.

Common mistakes โ€‹

  • Validating with a bare findOne and trusting whatever document comes first: filter by the full key of the data you created.
  • Assuming immediate consistency in distributed systems: active waits, not instant reads.
  • Ignoring "old" documents. Without forced schema migrations, different document versions coexist in the same collection; tests must account for that.

Key idea

In SQL the database defends the schema for you; in NoSQL the schema is a promise made by the code. And promises made by code are exactly what a QA is in the business of verifying.

References โ€‹