Skip to content

Instantly share code, notes, and snippets.

@tavurth
Last active September 6, 2020 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tavurth/ff00b90fee927208693107a7775c12d0 to your computer and use it in GitHub Desktop.
Save tavurth/ff00b90fee927208693107a7775c12d0 to your computer and use it in GitHub Desktop.
Fuzzy Testing
/**
* Original code, found in an inherited project
*/
function original(item, currentLocale) {
const { message } = item;
if (!message.translation) return true;
if (
message.translation.lastTranslated !== undefined &&
message.translation.locale === currentLocale
) {
if (message.lastEdited !== undefined && message.translation.lastMessageEdited !== undefined) {
if (message.translation.lastMessageEdited.getTime() !== message.lastEdited.getTime()) {
return true;
}
} else if (
(message.lastEdited !== undefined && message.translation.lastMessageEdited === undefined) ||
(message.lastEdited === undefined && message.translation.lastMessageEdited !== undefined)
) {
return true;
}
return false;
}
return true;
}
/**
* Refactored code
*/
function refactored(item, currentLocale) {
const { message = {} } = item;
const { translation, lastEdited } = message;
// ====================
if (!translation) return true;
if (!translation.lastTranslated) return true;
if (translation.locale !== currentLocale) return true;
// ====================
const { lastMessageEdited } = translation;
if (lastEdited && lastMessageEdited) {
return lastMessageEdited.getTime() !== lastEdited.getTime();
}
return Boolean(lastEdited) !== Boolean(lastMessageEdited);
}
// ==================================================
// Fuzzy testing begins below
// ==================================================
function assert(value) {
if (!value) {
throw new Error();
}
}
function describe(...args) {
const [test] = args.slice(-1);
try {
test();
} catch (error) {
args.slice(0, -1).forEach(item => console.info(item));
throw error;
}
}
function expect(argA) {
return {
toEqual(argB) {
try {
assert(argA === argB);
} catch (error) {
throw new Error(`Expected ${argA} toEqual ${argB}`);
}
},
};
}
function wrongReturn() {
return undefined;
}
function getLocale() {
const locales = ['en', 'ru', 'de', 'cz', 'us', 'thailand', wrongReturn()];
return locales[Math.floor(Math.random() * locales.length)];
}
function getResult() {
if (Math.random() > 0.5) return wrongReturn();
return Math.floor(Math.random() * 10);
}
function getEdited() {
if (Math.random() > 0.5) {
return wrongReturn();
}
const result = getResult();
return {
getTime() {
return result;
},
};
}
function getLastTranslated() {
return Math.random() > 0.5 ? undefined : 100;
}
function getTranslation() {
if (Math.random() > 0.5) {
return wrongReturn();
}
return {
locale: getLocale(),
lastMessageEdited: getEdited(),
lastTranslated: getLastTranslated(),
};
}
function getMessage() {
return {
lastEdited: getEdited(),
translation: getTranslation(),
};
}
const numberOfTests = 1000000;
for (let i = 0; i < numberOfTests; i++) {
const locale = getLocale();
const message = getMessage();
describe(message, locale, () => {
expect(original({ message }, locale)).toEqual(refactored({ message }, locale));
});
}
console.info();
console.info(`✔ ${numberOfTests} tests passed successfully!`);
console.info();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment