Lesson 5 of 14
Lesson 05 — Loops and nested data for QA automation
Title: for, while, for...of, for...in, break, and continue
Description: Loops are used to go through lists of data such as test datasets, table rows, API responses, and grids. This lesson explains different loop types: classic for, for...of for iterables, for...in for object keys, and while loops with manual control. It also covers break and continue, working with nested arrays and objects, and basic patterns like filtering and accumulation.
Why it matters for QA: Test automation often processes arrays from APIs, CSV files, or parameterized tests. Choosing the wrong loop can cause issues like skipping items, reading unexpected object keys, or incorrect indexing in arrays.
1. Classic for — counting up and by step
for (let step = 1; step <= 5; step++) {
console.log("step", step);
}
for (let odd = 1; odd <= 9; odd += 2) {
console.log(odd);
}
Count down:
for (let n = 8; n > 0; n--) {
console.log(n);
}
2. for...of — each element in an array
let caseIds = [101, 102, 103, 104, 105];
for (let id of caseIds) {
console.log(id);
}
Strings are iterable too — for...of yields each character:
let buildLabel = "QA-42";
for (let character of buildLabel) {
console.log(character);
}
3. for...in — keys of an object
let caps = { chromium: true, firefox: true, webkit: false };
for (let name in caps) {
console.log(name, caps[name]);
}
QA note: for...in enumerates inherited enumerable keys.
4. while
let backoff = 5;
while (backoff > 0) {
console.log("retry in", backoff);
backoff--;
}
5. Index loop over an array
let seeds = [10, 20, 30, 40, 50];
for (let i = 0; i < seeds.length; i++) {
console.log(i, seeds[i]);
}
6. Filter inside a loop (even values)
let scores = [11, 12, 13, 14, 15];
for (let score of scores) {
if (score % 2 === 0) {
console.log("even score", score);
}
}
7. Accumulator — sum 1 to N and sum of an array
let total = 0;
for (let k = 1; k <= 50; k++) {
total += k;
}
console.log(total);
let deltas = [2, 4, 6, 8, 10];
let sumDeltas = 0;
for (let d of deltas) {
sumDeltas += d;
}
console.log(sumDeltas);
8. break — stop when found
let markers = ["a", "b", "fail", "d"];
for (let marker of markers) {
if (marker === "fail") {
console.log("found failure marker");
break;
}
}
9. continue — skip this iteration, next one
continue jumps to the next iteration of the innermost loop. Use it to skip irrelevant rows without nesting everything in else.
let rows = ["ok", "skip", "ok", "bad"];
for (let row of rows) {
if (row === "skip") {
continue;
}
console.log("processing", row);
}
// logs: processing ok, processing ok, processing bad
10. Two-dimensional array (matrix)
let grid = [
["x1", "x2", "x3"],
["y1", "y2", "y3"],
["z1", "z2", "z3"],
];
console.log(grid[0][1]); // "x2"
console.log(grid[1][2]); // "y3"
11. Nested object — fixed access
let suites = {
api: { passed: 12, failed: 0, skipped: 1 },
ui: { passed: 8, failed: 1, skipped: 0 },
e2e: { passed: 3, failed: 0, skipped: 2 },
};
console.log(suites["api"].passed);
console.log(suites.ui.failed);
12. Array of objects — typical fixture
let accounts = [
{ login: "qa_alpha", role: "reader" },
{ login: "qa_beta", role: "admin" },
{ login: "qa_gamma", role: "editor" },
];
for (let account of accounts) {
console.log(account.login + " → " + account.role);
}
Official docs
Quick recap
| Goal | Construct |
|---|---|
| Values only | for (const x of arr) |
| Index + values | for (let i = 0; i < arr.length; …) |
| Object keys | for (const k in obj) or Object.keys |
| Stop early | break |
| Skip one step | continue |
Suggested exercises
- Sum only numbers greater than
10in[5, 12, 3, 99]. - Nested loop: print each cell of a
2×3matrix with row and column index. - Using
continue, print allusersexcept those withrole === "guest". - When would
for...inover an array be a bad idea? (Hint: sparse arrays and indices as strings.)
Homework
Short tasks (about 10–15 minutes). Click a task title to reveal the prompt.
Task 1: sum values above 10
For [3, 15, 2, 20], sum only elements strictly greater than 10 using a loop and an accumulator variable.
Task 2: print a 2×3 grid
Create a 2×3 matrix (two rows, three columns) of short string labels. Use nested loops to log each cell with its row and column index.
Task 3: skip guests
Given let users = [{ name: "Ann", role: "admin" }, { name: "Bob", role: "guest" }, { name: "Cia", role: "qa" }];, log names for everyone except role === "guest" using continue.
Task 4: classic for countdown
Use a for loop to log integers from 5 down to 1 (inclusive).
Task 5: while retries
Set let attempts = 3 and use while to log "try" once per remaining attempt, decrementing until attempts is 0.
Task 6: break on first failure
Loop ["pass", "pass", "fail", "pass"] with for...of and break as soon as you see "fail". Log how many items you inspected before stopping.
Task 7: keys with for...in
Given let caps = { chromium: true, firefox: true };, use for...in to log each browser name and its boolean. Then say in one sentence when Object.keys might be clearer.
Task 8: index with for...of entries
Given let ids = ["T-1", "T-2", "T-3"], loop with for (const [index, id] of ids.entries()) and log both index and id.
Task 9: early return from helper
Loop through ["ok", "ok", "fail", "ok"] using for...of. Save the first "fail" value into a variable and stop with break, then log that variable.