Skip to content

Cases as code

Cases can be kept in git as Markdown files (a folder is a suite, a file is a case) and synchronized with the server:

Окно терминала
pnpm tsmc pull -p SHOP -d qa/cases # write the project to a folder
pnpm tsmc push -d qa/cases --dry-run # what would change
pnpm tsmc push -d qa/cases # send it in one atomic operation

A push is refused as a whole if a case changed both in the file and on the server; a pull updates only untouched files and puts the server copy next to a conflicting one.

A project’s cases can live in git next to the product’s code: reviewed in pull requests, searched with grep, edited in your favourite editor — and synchronized with TSMC with tsmc pull / tsmc push.

qa/cases/ ← the folder given in --dir
.tsmc.json ← {"project": "SHOP"}: no --project needed after that
Checkout/ ← folder = suite
_suite.md ← suite id, name (if it has characters folders cannot hold), paths and description
SHOP-1 Pay by card.md ← file = case; the file name can be anything
Promo codes/ ← nested suite
expired.md ← a new case: it gets an id after push
---
id: SHOP-12
version: 3
priority: high # low | medium | high | critical
type: functional # functional | smoke | regression | acceptance | performance | security | usability | other
status: active # draft | active | deprecated
tags: [smoke, payments]
automation: checkout.PaymentTest.paysWithSavedCard
paths: [src/payments/**] # code the case checks — for picking by changes
---
# Pay with a saved card
## Description
The most common way to pay: about **60%** of orders.
## Preconditions
The user is signed in and has an item in the cart.
## Steps
1. @shared Sign in as a customer
2. Open the cart
> The cart is open
3. Click "Pay"
and choose the card {{card}}
> The payment form is shown
## Data
| card |
| --- |
| *1234 |
| *5678 |
  • A new file needs only the # Title heading; everything else has defaults.
  • tsmc writes id and version itself. version is the server version the file is based on.
  • A step is an item of a numbered list; continued action text is indented lines; the expected result is indented lines starting with >.
  • N. @shared Name is a shared step of the project (the “Shared steps” page): one line in the file, and the server fills in its steps on push by name. Its text is changed in the interface — then every case with it changes, and on the next pull the files stay the same: they still have one line.
  • ## Data holds the case’s parameters: a Markdown table with parameter names in the first row and then a row per iteration. {{name}} in the title, preconditions and steps is replaced with the value; in a run the case is executed once per row. A | inside a value is written as \|.
  • ## Description says what the case is about and why: context for whoever runs it. Optional, like every section.
  • Sections can be named in English or in Russian: ## Description / ## Описание, ## Preconditions / ## Предусловия, ## Steps / ## Шаги, ## Data / ## Данные. tsmc pull writes the Russian names.
  • Texts are Markdown: **bold**, *italic*, lists and tables (| a | b | with a | --- | --- | line) work in preconditions, actions and expected results; underline, fonts and sizes from the editor come as inline HTML: <u>…</u>, <span style="font-size: 18px">…</span> (only the fonts and sizes the editor offers are kept). A table in a step is indented like any continuation line, or follows > in the expected result.
  • Unknown sections and text outside sections are an error: the file is not sent until it is fixed. That way nothing is lost silently.

tsmc push sends the whole folder in one atomic operation:

State of the file Result
a new file without id the case is created, id and version are written into the file
changed, the server has not changed since version a new case version
unchanged nothing
unchanged, but the server has a newer version outdated — run tsmc pull
changed both in the file and on the server conflict — the push is refused as a whole
a case on the server, but no file missing; deleted only with --delete-missing

--dry-run shows what would change without changing anything.

tsmc pull brings the folder to the server’s state by comparing three versions (the file, its base version, the server): untouched files are updated and move along with their suites, files changed locally are kept. If a file changed on both sides, a copy from the server <file>.server is put next to it.

  1. Compare the file with <file>.server and carry the changes you need into the file.
  2. Set version in the file to the one from the copy.
  3. Delete the copy and run tsmc push.

tsmc pull --force instead overwrites local edits with the server version.

Окно терминала
# once
tsmc pull -p SHOP -d qa/cases && git add qa/cases && git commit -m "Import cases"
# everyday work: case edits go into the same PR as the code
vim "qa/cases/Checkout/SHOP-1 Pay by card.md"
tsmc push -d qa/cases --dry-run # in CI: check that the push will go through
tsmc push -d qa/cases # after the merge into main
git commit -am "Cases: updated ids and versions"

Limitations: in preconditions and steps, do not start a line with # (it would be read as a heading), and do not start a continuation line of an action with > (it would be read as the expected result).