Variables, Data Types, and console.log

8 min read

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 treats var as 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);  // undefined

In 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);  // null

The 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 it

The 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

(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:

  • testName
  • expectedStatusCode
  • isLoggedIn
  • maxRetries

Avoid:

  • TestName — looks like a class name
  • test_name — Python style; JavaScript code reviews flag it
  • tn — too cryptic
  • data — too vague (what data?)

Two more habits worth picking up:

  • Boolean variables read well with an is, has, or should prefix: 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. const doesn't just suggest immutability — it enforces it. Trying to reassign throws TypeError: Assignment to constant variable at runtime. If you genuinely need to change the value, switch the declaration to let.
  • Confusing strings and numbers. "200" === 200 is false because the types differ. Most flaky equality bugs in tests come from comparing values whose types you assumed but never checked. typeof is two seconds of insurance — and the assertion glossary entry covers why exact type matching matters in test code.
  • Forgetting to declare with const or let. 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.

  1. In your js-for-qa folder, create config.js.

  2. 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 be false for local runs (boolean)
    • currentUser — set to null (logged out) for now
  3. Add let testsPassed = 0; (it'll change as tests run).

  4. Print every variable with its typeof, like this:

    console.log("baseUrl:", baseUrl, "—", typeof baseUrl);
  5. Run with node config.js. Confirm the output shows the right type for each variable.

  6. Stretch: try to reassign a const (e.g., baseUrl = "..."). Watch JavaScript throw the error. Now switch that one declaration to let and confirm the reassignment works. You've just felt the difference between const and let directly.

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.

// tip to track lessons you complete and pick up where you left off across devices.