Reusing JavaScript Tests
Reusing JavaScript Tests - Bits and Pieces
Increasing test validity while decreasing costsWriting tests is hard. 😤Why do we need them in the first place? 🤔Code defines a set of instructions to perform a specific operation. Consider this function as performing the well-defined mathematical operation:y = a + b.Assuming the developer understands the underlying principles, he can write this correct implementation in machine code://seems about rightfunction Add(a,b) { return a + b;}However, noise from human error, system constraints, or other bugs may damage the code:function Add(a,b){ return a + ‘ ’ + b; //woops!}This is where tests come in. ✨Tests describe the operation in behavior-outcome language,mirroring the code’s machine language.Damaged code would be reflected as test failures:import Add;test(‘add should return the sum of two numbers’, () => {  expect(add(2,3)).toBe(5); //error! it is actually ‘2 3’!});Increase validity while decreasing costsMathematically, “regular” code is a continuous function, while tests are discrete samples of the same operation. Writing and maintaining a sample size big enough to ensure correctness could be just as difficult as writing the ‘regular’ code itself. 😞So why not reuse existing tests, as we do with our “regular” code? 😃Reusing testsI know, reusing tests is an awful experience.Developing in existing endless interwoven code is hard enough, no matter how well-written it is.If you ever dared to interweave tests, I bet you got a headache pretty quick.But, I can imagine at least one use case where this would be applicable:interface IFileSystem {  writeFile(path, content);  unlink(path)  …}//common file-system implementation:class NodeFs implements IFileSystem {  …}Most tests written for NodeFS, could, with little adaptation, be written for IFileSystem! 😯Another file system could have another implementation, and still, use the same tests!// memory-filesystem//———————————————// in memory file system for fast short and isolated uses.class NodeFs implements IFileSystem { …}//memory-filesystem.test//———————————————import FileSystemTestsimport MemFsFileSystemTests.validate(MemFs);Can we do it today?Yes! 🥳The cost of code isolation is falling, and even tests worth the effort.One of the most exciting tools in the domain of code isolation is Bit (Github). Bit is a tool and platform that helps you isolate code. Bit also offers a quick and easy way to share your isolated components to a collection in bit.dev, so that others (and your future-self) may use and even collaborate on. Bit is usually used for UI components, as a way to gradually build a UI component library but, it can easily be used for Node/JS utility functions and tests.Example: Shared components in bit.devWrite your test:import expect from ’chai’; //you gotta get it somewhereimport { IBinaryOperation } from ’math-functions’;import { toPairs } from ’combinatorics’;function validateAssociativity<T>(  operation: IBinaryOperation<T>,  values: T[]) {  toPairs(values).forEach((x, y) => {      expect(binaryOperation(x, y))    .toEqual(binaryOperation(y, x));  }}export validateAssociativity;2. Isolate the test into an atomic component using Bit:§ bit add AssociativeTests.Ts —-id math/tests/associativity§ bit add -c bit.envs/compilers/typescript§ bit tag math/tests/associativity3. Push your component to your collection in bit.dev:(learn how to create your Bit collection here)§ bit export collection.name math/tests/associativity3. Now we can easily reuse our shared reusable test component:import add from ’./add.js’;import { validateAssociativity } from ’@bit/collection.name.math.tests.associativity’;test(‘add associativity’, () => {const sample = [1, 5, 3, 1000, 0.3, -17];  // or maybe.. math/samples/realNumbers ..?validateAssociativity(add, sample);}Pretty neat! 🤯Will pngSnapshot components be the next hot thing? 🔮Could we have checklists like Accessibility support, FPS quota, and screen responsiveness?What do you think? 😍Learn More