Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

143
Views
Best Practices for TDD in JavaScript/TypeScript

Questions

  • What is the correct/acceptable way to access all JavaScript/TypeScript functions in a module for unit testing?
  • Is there a (good) reason why I shouldn't just export all my functions?

Context

Please forgive my ignorance; I have spent the majority of my professional career writing Python code using the Test Driven Development (TDD) approach. Now, I am finding myself learning ReactJS/TypeScript and figuring out how to implement unit tests, but I quickly found out that functions are only accessible if you export them. As most of you know, Python is very permissive; there really is no concept of privacy, so it's just a matter of importing the module and being respectful of what you have access to. But JavaScript only imports the functions of a module that have been explicitly exported, thus providing a modest barrier.

I've been told that it's not a great idea to export all my functions for testing, but I'm not aware of another way to actually be able to test them.

Examples

What I've been told is "correct/better":

Sample1.js:

const func1 = () => {
    //code that does stuff
    return "stuff";
};

const func2 = () => {
   //code that does other stuff
   return "otherStuff";
};

export { func1 };

Sample1.test.js:

// executed via Jest framework

import * as sample from "./Sample1.js"

describe("Unit Tests for Sample1", () => {
    test("Unit Test - func1", () => {
        // code that tests stuff
    };

    test("Unit Test - func2", () => {
        // can't test func2 because it's not exported
    };
};

What I'm doing to be able to test all functions:

Sample2.js:

const func1 = () => {
    //code that does stuff
    return "stuff";
};

const func2 = () => {
   //code that does other stuff
   return "otherStuff";
};

export { func1, func2 };

Sample2.test.js:

// executed via Jest framework

import * as sample from "./Sample2.js"

describe("Unit Tests for Sample2", () => {
    test("Unit Test - func1", () => {
        // code that tests stuff
    };

    test("Unit Test - func2", () => {
        // code that tests other stuff because it's exported
    };
};

For the Record

I've looked around on the internet and Stack Overflow specifically for standards and best practices, but I haven't found much that answers this specific question. The closest I found was this SO question, but it's not really what I'm after.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

If you're truly doing test-driven development (TDD) by writing the test before the System Under Test (SUT), then you can view the tests as an executable specification of the SUT. (I'm sorry if this is already obvious to you, but many people here on Stack Overflow use the term TDD interchangeably with unit testing, and say that they do TDD even though they write the tests after the SUT.)

Thus, the tests describe the API of the SUT. In languages with access modifiers and/or explicit export features, you'll need to make the SUT available to the tests. In JavaScript, this does mean that you'll have to export the API that you want to test. In other languages with access modifiers, this also means that you'll have to give the SUT API public availability (such as for example Java and C#).

If you're developing a library, this will also coincide with the API that's available to client code. In fact, tests are the first (or earliest) client of the SUT.

Once the tests are in place, they serve as a regression test suite for the SUT. Thus, if a test fails, it indicates to you that some part of the exported API is broken. This also implies that that part will be broken for client code that makes use of it.

Should you export all methods, then?

Not necessarily. You may want to keep some methods hidden as implementation details. There can be various good reasons for that. Perhaps you're not sure that the helper method's API is robust, and you want to reserve the ability to change it without breaking client code. Perhaps the helper method has poor encapsulation.

As long as such helper methods are created during the TDD process, they will still be transitively covered by tests even if they are not, themselves, exported.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!