Last active
September 6, 2020 18:52
-
-
Save tavurth/ff00b90fee927208693107a7775c12d0 to your computer and use it in GitHub Desktop.
Fuzzy Testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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