DEV Community

Mohamed Idris
Mohamed Idris

Posted on

"Deterministic": Same Question, Same Answer, Every Time

You run your tests. Green. You run them again, changing nothing. Red. You run a
third time. Green again. You haven't touched a thing, but the result keeps
flipping. Spooky, right?

That flickering test is not deterministic, and that one word explains a
whole family of frustrating bugs.


The idea in one line

Something is deterministic if the same input always gives the same output,
every single time.


The metaphor: a vending machine vs a slot machine

VENDING MACHINE                 SLOT MACHINE
press B4 -> always a cola       pull lever -> who knows?
   = DETERMINISTIC                 = NOT deterministic
Enter fullscreen mode Exit fullscreen mode

Press B4 on a vending machine and you get a cola. Always. Press it a thousand
times, a thousand colas. That's deterministic: predictable, repeatable, trustable.

A slot machine takes the same pull and gives you a different result each time.
Fun for gambling. Terrible for code you need to trust.


How it shows up in code

// NOT deterministic: depends on the clock and a dice roll
function makeId() {
  return Date.now() + "-" + Math.random()  // different every call
}

// Deterministic: same input -> same output, forever
function double(n) {
  return n * 2   // double(5) is 10. today, tomorrow, on any machine.
}
Enter fullscreen mode Exit fullscreen mode

double(5) is 10 and will be 10 until the end of time. But makeId() gives
you something new each call, because it leans on Date.now() and Math.random(),
two classic sources of "it depends."


A real case: flaky tests

The number one place juniors meet this word is flaky tests. A test that
passes and fails for no clear reason is usually leaning on something
non-deterministic:

  • The current time or date.
  • Random values.
  • The order results come back from an API or database.
  • Another test that ran first and left junk behind.
// Flaky: "today" changes, so this test rots over time
expect(formatDate(new Date())).toBe("2026-05-31")

// Stable: feed in a fixed input, get a fixed output
expect(formatDate(new Date("2026-05-31"))).toBe("2026-05-31")
Enter fullscreen mode Exit fullscreen mode

The fix is almost always the same: stop depending on the unpredictable thing.
Pass the date in. Lock the random seed. Sort the list before checking it.


Gotchas juniors hit

1. Hidden inputs.
A function can look pure but secretly read the clock, a global, or a file. Those
hidden inputs make it non-deterministic. Hunt them down.

2. Relying on order you were never promised.
"The database gives rows back in insert order" is not guaranteed unless you
ORDER BY. Don't trust luck.

3. Thinking random is bad.
It's not! You want randomness for IDs, salts, and shuffles. Just keep it out of
the parts you need to test and trust.


Recap

  • Deterministic = same input, same output, every time. Like a vending machine.
  • Non-deterministic = results that change on their own. Like a slot machine.
  • The usual culprits: time, randomness, order, and leftover state.
  • Flaky tests almost always hide a non-deterministic input.

Your turn

Look at your flakiest test (you know the one). What unpredictable thing does it
touch: the clock, a random value, or an order you never pinned down? Make that
input fixed, and watch it go calm. Then go explain "vending machine vs slot
machine" to a friend.

Top comments (0)