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

javascriptjavascript
for (let step = 1; step <= 5; step++) {
  console.log("step", step);
}

for (let odd = 1; odd <= 9; odd += 2) {
  console.log(odd);
}

Count down:

javascriptjavascript
for (let n = 8; n > 0; n--) {
  console.log(n);
}

2. for...of — each element in an array

javascriptjavascript
let caseIds = [101, 102, 103, 104, 105];
for (let id of caseIds) {
  console.log(id);
}

Strings are iterable too — for...of yields each character:

javascriptjavascript
let buildLabel = "QA-42";
for (let character of buildLabel) {
  console.log(character);
}

3. for...in — keys of an object

javascriptjavascript
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

javascriptjavascript
let backoff = 5;
while (backoff > 0) {
  console.log("retry in", backoff);
  backoff--;
}

5. Index loop over an array

javascriptjavascript
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)

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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.

javascriptjavascript
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)

javascriptjavascript
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

javascriptjavascript
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

javascriptjavascript
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

GoalConstruct
Values onlyfor (const x of arr)
Index + valuesfor (let i = 0; i < arr.length; …)
Object keysfor (const k in obj) or Object.keys
Stop earlybreak
Skip one stepcontinue

Suggested exercises

  1. Sum only numbers greater than 10 in [5, 12, 3, 99].
  2. Nested loop: print each cell of a 2×3 matrix with row and column index.
  3. Using continue, print all users except those with role === "guest".
  4. When would for...in over 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.