The bug that finally made me set up tests was a tax rounding error that quietly shipped wrong totals for two weeks. It lived in a plain function — no Sheets, no API — the kind of thing a single unit test would have caught in a second. But the project had zero tests, because the last person who tried had hit the wall everyone hits: Jest can't load SpreadsheetApp.

Apps Script is testable. You just can't test all of it the same way. Here's the four-layer approach I use, with the real code — and yes, I ran the examples in this post before publishing.

Why Jest and Vitest choke on Apps Script

Apps Script runs on Google's servers with global services — SpreadsheetApp, DriveApp, GmailApp, UrlFetchApp — that simply don't exist in Node. Point Jest or Vitest at a file that calls SpreadsheetApp.getActive() and it throws ReferenceError: SpreadsheetApp is not defined before a single assertion runs. Coverage tools like Istanbul have the same problem. The script editor, meanwhile, has no test runner at all.

So you don't test Apps Script as one thing. You split it into layers by what each layer needs to run.