Every test script starts with values: a base URL, a maximum timeout, a flag for "are we in production?", a list of test users. Those values are stored in variables — named containers that hold data. JavaScript also distinguishes between several kinds of data — strings, numbers, booleans — and knowing which kind you have prevents a huge class of test bugs. This lesson walks through both, with QA-specific examples throughout.
What a variable is
A variable is a name that points to a value. You declare it once, then refer to it by name everywhere else.
const baseUrl = "https://staging.myapp.com";
console.log(baseUrl);
console.log(baseUrl + "/login");Output:
https://staging.myapp.com
https://staging.myapp.com/login
Without the variable, you'd be typing the URL out everywhere — and missing one when the staging hostname changes. With the variable, you change one line.
let, const, and var
JavaScript has three keywords for declaring variables. You only need two.
const— a constant. The value cannot be reassigned to a different value. Use this by default.let— a mutable variable. The value can be reassigned later. Use this when you genuinely need the value to change.var— the original (1995) keyword. It has scope and hoisting quirks that bite. Modern JavaScript treatsvaras legacy. You'll see it in old code; don't use it in new code.
const baseUrl = "https://staging.myapp.com"; // never reassigned
let testsPassed = 0; // increments as tests run
testsPassed = testsPassed + 1; // legal — declared with let
const maxRetries = 3;
maxRetries = 5; // ❌ TypeError: Assignment to constant variable.A useful rule: write const first, and only switch to let when JavaScript complains. That habit alone catches a lot of accidental-mutation bugs.
Data types
JavaScript has a small set of built-in types you'll meet immediately.
String — text
Strings hold text. Always wrap them in quotes — "double", 'single', or `backticks` (backticks let you embed ${expressions}).
const testName = "Login with valid credentials";
const env = 'staging';
const url = `https://${env}.myapp.com`;
console.log(testName, url);Output:
Login with valid credentials https://staging.myapp.com
Number — integers and decimals
Numbers don't take quotes. There's no separate int and float like in some other languages — every number is a Number.
const statusCode = 200;
const timeoutSeconds = 30;
const passRate = 87.5;
console.log(statusCode, timeoutSeconds, passRate);A subtle gotcha for QA: an HTTP status code returned by fetch().status is a number, but the same value read from a JSON response field is sometimes a string depending on the API. The two won't be equal under ===. Always check.
Boolean — true or false
Booleans hold one of exactly two values: true or false. They model yes/no decisions in test code: is the user logged in, has the page loaded, should this test be skipped.
const isLoggedIn = true;
const isProduction = false;
const isDarkMode = true;
console.log(isLoggedIn, isProduction);Undefined — declared but not assigned
If you declare a variable and don't give it a value, it's undefined. The same value also appears when a function doesn't return anything, or when you read a property that doesn't exist on an object.
let nextTest;
console.log(nextTest); // undefinedIn practice, undefined is the value beginners see most often when something has gone wrong — usually because they forgot to assign a value, or expected an API to return data that wasn't there.
Null — intentionally empty
null is similar to undefined but means "deliberately set to nothing." If a user has no middle name in your test data, that field would be null, not the empty string "" and not undefined.
const middleName = null;
console.log(middleName); // nullThe semantic difference: undefined is "JavaScript hasn't given me a value." null is "I'm telling JavaScript the value is nothing." Both feel similar; the distinction matters in API contract testing.
typeof — what type is this?
The typeof operator returns the type of any value as a string. It's the fastest way to debug "why isn't my assertion matching?"
console.log(typeof "Login"); // string
console.log(typeof 200); // number
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object ← historical bug, just remember itThe typeof null === "object" quirk is a 30-year-old mistake in the language that everyone agreed to leave alone for compatibility. Memorise it once and move on.
The data types at a glance
JavaScript primitive types — QA-flavoured examples
(Each bar is the same height — the chart is a labelled cheat-sheet of the five primitive types you'll meet in QA work, with a typical example per type.)
Naming variables
JavaScript's standard convention is camelCase — start with a lowercase letter, capitalise each subsequent word.
Good:
testNameexpectedStatusCodeisLoggedInmaxRetries
Avoid:
TestName— looks like a class nametest_name— Python style; JavaScript code reviews flag ittn— too crypticdata— too vague (what data?)
Two more habits worth picking up:
- Boolean variables read well with an
is,has, orshouldprefix:isAdmin,hasAccess,shouldRetry. The reader can pronounce the variable as a yes/no question. - Constants representing fixed configuration are sometimes written in
SCREAMING_SNAKE_CASE(e.g.,const MAX_RETRIES = 3). Both styles are common — pick one and be consistent within a project.
A real QA config
Pulling everything together. Here is the kind of config a real test suite uses, written with all the conventions of this lesson:
const baseUrl = "https://staging.myapp.com";
const apiKey = "test-1234-abcd";
const maxRetries = 3;
const defaultTimeoutMs = 10000;
const isProduction = false;
const currentUser = null; // logged out
let testsPassed = 0; // increments as tests run
console.log(`Running against ${baseUrl} (production: ${isProduction})`);
console.log(`Retries: ${maxRetries}, timeout: ${defaultTimeoutMs}ms`);Output:
Running against https://staging.myapp.com (production: false)
Retries: 3, timeout: 10000ms
Every variable is declared with the right keyword, named in the right convention, and given the right type. This is the shape of code that's easy to read in six months.
⚠️ Common mistakes
- Reassigning a
const.constdoesn't just suggest immutability — it enforces it. Trying to reassign throwsTypeError: Assignment to constant variableat runtime. If you genuinely need to change the value, switch the declaration tolet. - Confusing strings and numbers.
"200" === 200isfalsebecause the types differ. Most flaky equality bugs in tests come from comparing values whose types you assumed but never checked.typeofis two seconds of insurance — and the assertion glossary entry covers why exact type matching matters in test code. - Forgetting to declare with
constorlet. In old JavaScript,myVariable = 5(no keyword) silently created a global variable. Modern code in strict mode (the default for ES modules and most frameworks) throws an error instead. Always declare.
🎯 Practice task
Build a config file for a fictional test suite. 15-20 minutes.
-
In your
js-for-qafolder, createconfig.js. -
Declare these variables, choosing reasonable values:
baseUrl— the URL of the staging environment (string)apiKey— a fake key like"test-1234-abcd"(string)maxRetries— number of times a test retries on failure (number)defaultTimeout— milliseconds before a request gives up (number)isProduction— should always befalsefor local runs (boolean)currentUser— set tonull(logged out) for now
-
Add
let testsPassed = 0;(it'll change as tests run). -
Print every variable with its
typeof, like this:console.log("baseUrl:", baseUrl, "—", typeof baseUrl); -
Run with
node config.js. Confirm the output shows the right type for each variable. -
Stretch: try to reassign a
const(e.g.,baseUrl = "..."). Watch JavaScript throw the error. Now switch that one declaration toletand confirm the reassignment works. You've just felt the difference betweenconstandletdirectly.
The next chapter moves into control flow — making your code do different things depending on conditions. The variables and types you've just learned are the values you'll be making decisions about.