Run End-to-End Tests from Your Terminal with Kane CLI
Author and Run Tests Right from the Terminal in Natural Language, with an Evidence-Backed Pass or Fail from a Real Browser.
npm install -g @testmuai/kane-cli
- TestMu AI (Formerly LambdaTest)
- /
- Learning Hub
- /
- EARS Requirements Notation: Patterns, Examples and How to Test Each One
EARS Requirements Notation: Patterns, Examples and How to Test Each One
EARS notation in plain words: the five requirement patterns with examples, how Kiro writes EARS, the common mistakes, and the test oracle each pattern becomes.
Published on:
OVERVIEW
A requirement such as "the checkout page shall handle declined cards appropriately" can pass a document review and still leave the tester to decide what a pass looks like. EARS notation gives every requirement the same clause order, ending in a system response a test can check, so that decision is made when the requirement is written.
EARS, the Easy Approach to Requirements Syntax, was published in 2009 by Alistair Mavin, Philip Wilkinson, Adrian Harwood and Mark Novak at RE'09, the 17th IEEE International Requirements Engineering Conference in Atlanta. The paper's abstract, on the University of Manchester research record, says the authors built a small set of structural rules to address eight common requirement problems, including ambiguity, complexity and vagueness, and applied them to aero engine control system requirements taken from an airworthiness regulation.
Overview
EARS notation (Easy Approach to Requirements Syntax) is a set of sentence templates for writing requirements, developed by Alistair Mavin and colleagues at Rolls-Royce and first published in 2009. Every requirement keeps one clause order: an optional WHILE state, an optional WHEN trigger, the system name, shall, and the system response, which is the part a test checks.
What Are the 5 EARS Patterns?
- Ubiquitous: An EARS requirement with no keyword that is always active, such as "The checkout page shall display every price in the store's currency." It suits units, formats and limits that hold everywhere.
- State-driven: An EARS requirement that starts with WHILE and applies for as long as a state is true, such as an empty cart keeping the Pay button disabled.
- Event-driven: An EARS requirement that starts with WHEN and states the response to a trigger, such as a user applying a discount code and the checkout page showing the discounted total.
- Optional feature: An EARS requirement that starts with WHERE and applies only in products that include a feature, such as a store with gift wrapping enabled showing a Gift wrap option.
- Unwanted behaviour: An EARS requirement written with IF and THEN that states the response to an undesired situation, such as a declined card producing a "Payment declined" message.
Can EARS Requirements Be Tested Automatically?
Yes, when the response after shall names something a test can observe: an exact message, a value, a page or a control state. The precondition becomes setup, the trigger becomes the action, and the response becomes the assertion. TestMu AI's Kane CLI designs browser tests from a requirements file and records a gap when a promise has no stated expected result.
What Is EARS Notation?
EARS notation is a lightweight syntax for natural-language requirements: a few keywords mark the clauses of a requirement, and the clauses always appear in the same order. Alistair Mavin's EARS page describes it as "a mechanism to gently constrain textual requirements" and gives this generic template, shown here on two lines:
While <optional pre-condition>, when <optional trigger>,
the <system name> shall <system response>The same page sets out the ruleset every EARS requirement follows, and each clause maps to one part of a test:
- Preconditions - zero or many. A precondition, introduced by While, says when the requirement applies, and a test turns it into setup.
- Trigger - zero or one. The trigger, introduced by When, is the event that starts the behaviour, and a test turns it into an action.
- System name - exactly one, so every requirement names the system or component responsible for the response.
- System responses - one or many. A response says what must be true afterwards, and a test turns it into an assertion.
Mavin's page says the clause order follows temporal logic and that "no specialist tool is necessary", so an EARS requirement can live in a Word document, a Jira ticket or a Markdown file. It lists Airbus, Bosch, Dyson, Honeywell, Intel, NASA, Rolls-Royce and Siemens among the organisations that use EARS.
The 2009 abstract states that the ruleset "allows all natural language requirements to be expressed in one of five simple templates", and that its case study showed "qualitative and quantitative improvements compared with a conventional textual requirements specification."
What Are the Five EARS Patterns?
The five EARS patterns are ubiquitous, state-driven, event-driven, optional feature and unwanted behaviour. Each adds its keyword to the base sentence of a system name, shall and a response: no keyword, While, When, Where, or If with Then. A requirement that uses more than one keyword is what Mavin's page calls a complex requirement.
The example column marks each clause by the part of a test it becomes: setup for a state or feature, trigger for the event, and system response for what the test asserts. Keywords are in capitals to make the clauses easy to find; Mavin's page writes them in sentence case.
| Pattern | Keyword | Template | Example (checkout page) |
|---|---|---|---|
| Ubiquitous | None | The <system name> shall <system response> | The checkout page shall display every price in the store's currency. |
| State-driven | WHILE | While <precondition(s)>, the <system name> shall <system response> | WHILE the cart is empty, the checkout page shall disable the Pay button. |
| Event-driven | WHEN | When <trigger>, the <system name> shall <system response> | WHEN the user applies a valid discount code, the checkout page shall show the discounted total. |
| Optional feature | WHERE | Where <feature is included>, the <system name> shall <system response> | WHERE gift wrapping is enabled for the store, the checkout page shall show a Gift wrap option. |
| Unwanted behaviour | IF and THEN | If <trigger>, then the <system name> shall <system response> | IF the payment provider declines the card, THEN the checkout page shall show "Payment declined" and keep the cart unchanged. |
| Complex | Two or more | While <precondition(s)>, When <trigger>, the <system name> shall <system response> | WHILE the user is signed out, WHEN the user selects Pay, the checkout page shall redirect to /sign-in. |
The templates are from Mavin's EARS page, and the checkout examples were written for this guide. The same six lines are REQ-01 to REQ-06 in the script input further down. Pick the pattern from the shape of the behaviour:
- Ubiquitous - for properties that hold everywhere, such as units, formats and limits. If the property only applies after an action, the requirement is event-driven.
- State-driven - for behaviour that lasts as long as a mode or state does: signed out, offline, cart empty or maintenance mode.
- Event-driven - for most feature behaviour: something a user or another system does, and what the system does in reply.
- Optional feature - for product variants, plans and configuration flags, where one build has the feature and another does not.
- Unwanted behaviour - for errors, failures and misuse, such as declined payments, timeouts and invalid input. Without the THEN clause, the requirement has no response to check.
- Complex - for behaviour that needs a state and a trigger together. Mavin's page notes that complex requirements for unwanted behaviour also include IF and THEN.
How Does Kiro Use EARS in requirements.md?
Kiro, Amazon's AI development tool with an IDE, a CLI and a web app, writes the requirements file of each feature spec in EARS. Its requirements-first workflow docs say a generated requirements.md includes "System behaviors in EARS format (WHEN...THE SYSTEM SHALL...)" and describe EARS requirements as "Unambiguous and testable" and "Easy to translate into test cases". The same page shows these example requirements (page updated September 25, 2026, read November 5, 2026):
WHEN a user submits valid registration data
THE SYSTEM SHALL create a new user account
WHEN a user submits an email that already exists
THE SYSTEM SHALL display "Email already registered" error- Event-driven form - Kiro puts WHEN and THE SYSTEM SHALL on separate lines, with THE SYSTEM as the system name and a line break where EARS puts a comma. Kiro's feature specs page gives the pattern as WHEN [condition/event] THE SYSTEM SHALL [expected behavior].
- Ubiquitous lines - Kiro's correctness docs quote a requirement with no WHEN clause, "THE System SHALL allow authenticated users to view active car listings", as an example of an EARS-formatted requirement.
- Spec folders - each spec is a folder under
.kiro/specs/holdingrequirements.md(orbugfix.mdfor a bug),design.mdandtasks.md, and Kiro's best practices page recommends separate specs for different features rather than one for the whole codebase. - Property-based tests - the correctness docs say Kiro "extracts properties from your EARS-formatted requirements", decides which can be logically tested, and generates hundreds or thousands of random test cases when you choose to run them. These tests are optional by default.
The two example requirements show what the response clause decides. The response 'display "Email already registered" error' names an exact message, so a test can assert it. The response 'create a new user account' names an effect with nothing on screen, so a browser test has to choose its own proof: a welcome page, a sign-in that works with the new details, or a row in an admin list.
A property-based test checks a rule against generated inputs in code, and a browser test checks what a user sees in the running app, so the two catch different failures. Kiro's correctness docs note that requirements depending heavily on external services or non-deterministic behaviour "may need mocking, or may be better covered by example-based tests."
Writing the spec before the code is the approach covered in spec driven development, and Kiro is compared with other spec toolkits in spec-driven development tools.
How Do You Turn an EARS Requirement Into a Test?
Map each EARS clause to one part of a test. The precondition (While or Where) becomes the setup, the trigger (When or If) becomes the action, and the response after shall becomes the assertion, which is the test oracle: the check that decides pass or fail. If the response names no value, message, page or state, the requirement has no oracle yet.
| EARS pattern | What the test sets up | Test oracle (what decides pass or fail) | Example assertion |
|---|---|---|---|
| Ubiquitous | Several normal states (one item, many items, a discount applied) | The property holds in every state checked | In each state, every price on the checkout page shows the store's currency symbol |
| State-driven (WHILE) | Enter the state (empty the cart), then leave it | The response holds during the state and stops after it ends | With an empty cart the Pay button is disabled; after adding an item it is enabled |
| Event-driven (WHEN) | The preconditions for the trigger (a cart worth 50.00) | The response appears after the trigger and not before it | After applying SAVE10 to the 50.00 cart, the order total reads 45.00 |
| Optional feature (WHERE) | Two configurations: feature on and feature off | The response is present only when the feature is on | With gift wrapping on, a Gift wrap option is visible; with it off, it is not |
| Unwanted behaviour (IF ... THEN) | Force the fault (a sandbox card that always declines) | The error response appears and nothing else changes | The page shows "Payment declined" and the cart still holds the same items |
| Complex (WHILE and WHEN) | Enter the state, then cause the trigger | The response happens only in that state | Signed out, selecting Pay lands on /sign-in; signed in, it does not |
SAVE10 and 50.00 are test data the tester picks; the requirement itself stays general. For features with no single expected output, such as AI-generated text, the test oracle problem covers the checks that replace an exact assertion.
Read the table as a review checklist for each requirement:
- Something to look at for every shall - a message in quotes, a number, a URL, an enabled or disabled control, or a record that exists. If you cannot fill in the assertion column for a requirement, rewrite the requirement before anyone writes its test.
- Two checks for state and optional patterns - one where the condition holds and one where it does not. With only the first, a test also passes on a system that shows the response all the time.
- One assertion per response - EARS allows one or many responses, so the unwanted behaviour example, 'show "Payment declined" and keep the cart unchanged', is two checks, and either can fail on its own.
An EARS line plays the part of an acceptance criterion, and the test derived from it is the acceptance test; acceptance criteria vs acceptance tests covers where one ends and the other starts.
Kane CLI, TestMu AI's terminal testing agent, applies the first check when it designs tests from requirements. Its test design docs say that if the source never states the expected result for a promise, the engine records a missing-expected-result gap with a recommended default "instead of inventing an answer", and that a check which disagrees with its criterion is rejected. The default waits for your review, because nothing the engine proposes is trusted until you approve it.
Which EARS Mistakes Make a Requirement Untestable?
The EARS mistakes that make a requirement untestable are a response with no observable result, a vague word, two triggers in one requirement, IF without THEN, a trigger a test cannot cause, an implementation choice written as behaviour, a missing system name and "should" in place of shall. Each can pass a format review and still leave the tester guessing what a pass means.
| Mistake | Written as | Rewritten as |
|---|---|---|
| No observable result | WHEN the user places an order, the checkout service shall create the order. | WHEN the user places an order, the checkout page shall show the confirmation page with an order number. |
| Vague word | WHEN the user changes a quantity, the cart page shall update the total quickly. | WHEN the user changes a quantity, the cart page shall show the new total within 1 second. |
| Two triggers | WHEN the user applies a code or removes an item, the cart page shall show the new total. | Two requirements, one per trigger, since the EARS ruleset allows zero or one trigger. |
| IF without THEN | IF the stock check fails the cart page shall show "Out of stock". | IF the stock check reports an item out of stock, THEN the cart page shall show "Out of stock" beside that item. |
| Trigger a test cannot cause | WHEN the server is under heavy load, the checkout service shall queue new orders. | WHEN more than 500 order requests arrive within one second, the checkout service shall queue new orders. |
| Implementation, not behaviour | The cart service shall use Redis to store carts. | WHEN a signed-in user returns within 7 days, the cart page shall show the items left in the cart. |
| Missing system name | WHEN the user selects Pay, shall show the order confirmation. | WHEN the user selects Pay, the checkout page shall show the order confirmation. |
| "Should" in place of shall | The signup form should reject an email with no @ sign. | IF the email has no @ sign, THEN the signup form shall show "Enter a valid email". |
The load trigger in the rewritten row is something a load test can cause and a browser test cannot, so record which kind of test owns it. The numbers in the rewrites are placeholders: use the limits your product team agrees to.
A Node.js Script That Flags Untestable EARS Lines
A dependency-free Node.js script written for this guide checks a requirements file line by line. It tags each line's EARS pattern from its keywords and flags six of the mistakes above: no observable result, a vague word, two triggers joined by "or", IF without THEN, a missing system name and a missing shall. It was run on November 5, 2026 with Node.js v25.5.0 on Windows 11.
// ears-lint.mjs: tags the EARS pattern of each
// requirement and flags wording that leaves a test
// without an oracle.
// Usage: node ears-lint.mjs requirements.md
import { readFileSync } from 'node:fs';
const KEYS = ['where', 'while', 'when', 'if'];
const NAMES = { where: 'Optional', while: 'State-driven',
when: 'Event-driven', if: 'Unwanted' };
const VAGUE = ['quickly', 'fast', 'easy', 'appropriate',
'appropriately', 'user-friendly', 'efficiently'];
const SEEN = ['show', 'display', 'disable', 'enable',
'redirect', 'send', 'hide', 'keep', 'update'];
function check(text) {
const t = text.toLowerCase();
const at = t.indexOf(' shall ');
if (at < 0) {
const alt = ['should', 'must', 'will']
.find((w) => t.includes(' ' + w + ' '));
const note = alt ? ' (found "' + alt + '")' : '';
return { name: 'none', flags: ['no "shall"' + note] };
}
const clauses = t.slice(0, at).split(',')
.map((c) => c.trim());
const keys = clauses.map((c) => c.split(' ')[0])
.filter((w) => KEYS.includes(w));
const name = keys.length === 0 ? 'Ubiquitous'
: keys.length > 1 ? 'Complex' : NAMES[keys[0]];
const flags = [];
const subject = clauses.at(-1).replace(/^then /, '');
if (keys.includes('if') &&
!clauses.some((c) => c.startsWith('then '))) {
flags.push('IF without THEN');
} else if (!subject ||
KEYS.includes(subject.split(' ')[0])) {
flags.push('no system name before shall');
}
const trigger = clauses.find((c) =>
c.startsWith('when ') || c.startsWith('if '));
if (trigger && trigger.includes(' or ')) {
flags.push('two triggers joined by "or"');
}
const response = t.slice(at + 7);
const words = response.split(' ')
.map((w) => w.replace('.', ''));
const vague = words.find((w) => VAGUE.includes(w));
if (vague) flags.push('vague word "' + vague + '"');
const visible = /["0-9/]/.test(response) ||
words.some((w) => SEEN.includes(w));
if (!visible) flags.push('no observable result');
return { name, flags };
}
const file = process.argv[2] || 'requirements.md';
const reqs = readFileSync(file, 'utf8').split('\n')
.map((l) => l.trim())
.filter((l) => l.startsWith('- REQ-'));
const day = new Date().toISOString().slice(0, 10);
console.log('ears-lint | ' + day + ' | Node.js ' +
process.version);
console.log('Input: ' + file + ', ' + reqs.length +
' requirements');
console.log('');
let flagged = 0;
for (const line of reqs) {
const cut = line.indexOf(':');
const id = line.slice(2, cut);
const req = line.slice(cut + 1).trim();
const { name, flags } = check(req);
if (flags.length) flagged++;
const verdict = flags.length
? 'FLAG ' + flags.join('; ') : 'ok';
console.log(id.padEnd(7) + name.padEnd(13) + verdict);
}
console.log('');
const ok = reqs.length - flagged;
console.log('Summary: ' + reqs.length + ' checked, ' +
ok + ' ok, ' + flagged + ' flagged');
process.exitCode = flagged ? 1 : 0;The input, requirements.md, holds the six pattern examples from the table above as REQ-01 to REQ-06 and six lines with one mistake each as REQ-07 to REQ-12:
## Checkout requirements
- REQ-01: The checkout page shall display every price in the store's currency.
- REQ-02: WHEN the user applies a valid discount code, the checkout page shall show the discounted total.
- REQ-03: WHILE the cart is empty, the checkout page shall disable the Pay button.
- REQ-04: IF the payment provider declines the card, THEN the checkout page shall show "Payment declined" and keep the cart unchanged.
- REQ-05: WHERE gift wrapping is enabled for the store, the checkout page shall show a Gift wrap option.
- REQ-06: WHILE the user is signed out, WHEN the user selects Pay, the checkout page shall redirect to /sign-in.
- REQ-07: WHEN the user places an order, the checkout service shall create the order.
- REQ-08: WHEN the user changes a quantity, the cart page shall update the total quickly.
- REQ-09: WHEN the user applies a code or removes an item, the cart page shall show the new total.
- REQ-10: IF the stock check fails the cart page shall show "Out of stock".
- REQ-11: WHEN the user selects Pay, shall show the order confirmation.
- REQ-12: The signup form should reject an email with no @ sign.Running node ears-lint.mjs requirements.md printed:
ears-lint | 2026-11-05 | Node.js v25.5.0
Input: requirements.md, 12 requirements
REQ-01 Ubiquitous ok
REQ-02 Event-driven ok
REQ-03 State-driven ok
REQ-04 Unwanted ok
REQ-05 Optional ok
REQ-06 Complex ok
REQ-07 Event-driven FLAG no observable result
REQ-08 Event-driven FLAG vague word "quickly"
REQ-09 Event-driven FLAG two triggers joined by "or"
REQ-10 Unwanted FLAG IF without THEN
REQ-11 Event-driven FLAG no system name before shall
REQ-12 none FLAG no "shall" (found "should")
Summary: 12 checked, 6 ok, 6 flagged- REQ-07 - "create the order" names no message, value, page or control, the same gap as the "create a new user account" line in Kiro's example.
- REQ-08 - "update" counts as observable, but "quickly" gives the assertion no number to compare against.
- REQ-10 - without THEN or a comma, neither the script nor a reader can tell where the trigger ends and the system name starts.
- Exit code - the script sets exit code 1 when any line is flagged, so a CI job can fail on it; this run flagged 6 of 12 lines.
The script reads keywords and two short word lists, so it can flag a line for the wrong reason or pass a line a reviewer would reject; add your own product's verbs to the observable list. It reads only lines that start with "- REQ-" and expects a comma before the system name, so join Kiro's two-line WHEN and THE SYSTEM SHALL format onto one line first. It is a standalone illustration, not a TestMu AI product.
Note: Kane CLI from TestMu AI runs the checks you derive from EARS requirements in a real Chrome browser and seals the evidence of every run. Create a free TestMu AI account
What Is the Difference Between EARS and Gherkin?
EARS states a requirement as one rule ("WHEN X, the system shall Y"), and Gherkin describes one concrete example of a rule as a scenario ("Given ... When ... Then ..."). EARS suits requirement documents, where a line has to hold for every valid input, and Gherkin suits executable examples with real values. One way to combine them is an EARS requirement with a few Gherkin scenarios under it, starting with the happy path and the main failure.
| Aspect | EARS | Gherkin |
|---|---|---|
| Unit | One requirement | One example scenario |
| Shape | When <trigger>, the <system name> shall <system response> | Given <context> When <action> Then <outcome> |
| Values | General ("a valid discount code") | Concrete ("SAVE10", "45.00") |
| Typical home | Requirement documents and Kiro's requirements.md | .feature files and Given/When/Then acceptance scenarios |
| Executable | No, a test has to be derived from it | Yes, with step definitions in a tool such as Cucumber |
| Error paths | The IF ... THEN pattern | A separate scenario for each failure |
The same discount rule in both forms:
EARS
WHEN the user applies a valid discount code,
the checkout page shall show the discounted total.
Gherkin
Scenario: Apply SAVE10 to a 50.00 cart
Given a cart totalling 50.00
When the user applies code "SAVE10"
Then the order total shows "45.00"The EARS line says a test is needed, and the Gherkin scenario says which values to test it with. Some spec templates already pair the two: OpenSpec's template writes a requirement with SHALL and puts WHEN/THEN scenarios under it.
Writing the scenarios themselves is covered in Gherkin testing, and acceptance criteria examples gives criteria for 16 user stories in both the rule-oriented and the Given/When/Then format.
Where Should EARS Sit in a Requirements Document?
EARS belongs in the functional requirements section of a software requirements specification, one requirement per line, each with an ID. Context, goals and user stories stay in prose above it, and acceptance examples go below. Kiro's requirements.md uses a similar mix: user stories with acceptance criteria, and system behaviours in EARS format.
## Functional requirements
- REQ-CART-01: WHEN the user applies a valid discount
code, the checkout page shall show the discounted
total.
- REQ-CART-02: IF the discount code has expired, THEN
the checkout page shall show "This code has expired".
- REQ-CART-03: WHILE the cart is empty, the checkout
page shall disable the Pay button.Those IDs are what a requirements traceability matrix links tests to, and they let a failed test name the requirement it broke. For the rest of the document, from scope to non-functional requirements, see how to write software requirement specifications.
- Stable IDs - never renumber a requirement; retire its ID and add a new one, so old test results still point at the right line.
- One line, one requirement - a line with two triggers becomes two IDs, and each gets its own tests.
- Glossary for system names - define "the checkout page" and "the checkout service" once, so every requirement names a component a tester can find.
How Can You Test EARS Requirements With Kane CLI?
Kane CLI, the terminal testing agent from TestMu AI, turns a requirements document into browser tests, with a link from every check back to the criterion it proves. A requirements.md written in EARS is a Markdown file, and kane-cli context ingest accepts Markdown like any other requirement document.
- Ingest -
kane-cli context ingest requirements.mdsaves a snapshot of the file, identified by a hash of its bytes, in a local.context/store, and on a terminal continues into a chat where an AI agent extracts use-cases from it (context graph docs). - Review -
kane-cli context reviewpromotes the extracted use-cases you approve. Extraction is an AI agent's work, so check each use-case against your EARS lines here. - Design -
kane-cli design tests --use-case <uc-id>writes acceptance criteria with oracles, scenarios and exactly one test per scenario as*_test.mdfiles, pausing after each phase for your approval. Where the requirements leave a value out, such as a store URL, the test uses a variable like{{store_url}}for you to fill in. - Tag - in each designed file every step is an H2 heading, and an assert step's heading lists, after a
@verifiestag, the acceptance criteria that step proves. The link is captured when the test is written. - Run -
kane-cli testrun runruns every*_test.mdfile under the current folder as one suite in Chrome, with one summary, one exit code and one sealed evidence pack. - Report -
kane-cli coverreads the newest evidence pack and shows which acceptance criteria that run proved, next to what the design still owes.
npm install -g @testmuai/kane-cli
kane-cli login
kane-cli context ingest requirements.md
kane-cli context review
kane-cli design tests --use-case <uc-id>
kane-cli testrun run
kane-cli coverThe npm install needs Node.js 18 or newer and Google Chrome, and the Homebrew install on macOS and Linux needs no Node and bundles Chrome, according to the Kane CLI installation docs. Kane CLI is free to install. Extraction, test design and test runs use KaneAI credits, while list, review, explain and cover run locally at no cost, and new users can claim 10,000 credits, valid for 30 days, on TestMu AI's Kane CLI product page.
TestMu AI's walkthrough of how to use Spec Kit with Claude Code from the command line shows the same ingest, design and run loop on a Spec Kit spec, with real output from kane-cli 0.8.18. If you build in Kiro, the guide to add real-browser verification with Kane CLI sets up a Kiro power so that Kiro's agent can run these checks itself.
Which EARS Requirements Should You Rewrite First?
Start with the lines a test cannot judge: run the script above over your requirements file and rewrite each flagged line until you can state its expected result in one sentence. Then give every WHILE and WHERE requirement its second check, and every requirement an ID that a test can point to.
When the file is clean, ingest it with Kane CLI and design tests from it; the Kane CLI quickstart covers installing and signing in.
Author
Sirajuddin Khan is Vice President of Product Management at TestMu AI, where he drives the company's agentic AI product strategy, building a suite of autonomous agents that includes Agentic Browsers and Agentic Visual Testing and shifting the unit of work from test execution to autonomous outcomes. One of the company's earliest product leaders, he has owned the roadmap for the high-performance execution cloud and grew the cross-browser testing products from early adoption to market leadership. He brings over a decade of experience across SaaS, B2B, and eCommerce, with earlier product roles at Wydr and ShopClues, where his catalog and search work cut delivery SLAs and lifted seller activity. Sirajuddin holds an MBA in Information Technology from Sikkim Manipal University and a B.Tech in Computer Science Engineering from Maharshi Dayanand University.
Reviewer
Mayank Bhola is Co-Founder and Head of Products at TestMu AI, where he leads the entire product portfolio across KaneAI, Kane CLI, HyperExecute, SmartUI, the Real Device Cloud, Accessibility, and other software testing product lines. As an early Lead Architect he designed and built the company's flagship Tunnel technology from scratch, created the React-based automation platform, and architected the data-intensive pipelines and FAAS services that scale it. He brings more than 10 years of experience in software development and product engineering, with earlier roles as Head of Technology at Juggernaut Books and Senior Software Engineer at PressPlay TV and Zomato. Mayank holds a B.Tech in Computer Engineering from JIIT Noida.
EARS Notation FAQs
Did you find this page helpful?
More Related Learning Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance
- Advanced access controls
- Advanced data retention rules
- Advanced Local Testing
- Premium Support options
- Early access to beta features
- Private Slack Channel
- Unlimited Manual Accessibility DevTools Tests





