Skip to content

Instantly share code, notes, and snippets.

@adamcameron
Created October 31, 2021 22:18
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 adamcameron/b4e795c7b38c6698d95ea06dfd183f38 to your computer and use it in GitHub Desktop.
Save adamcameron/b4e795c7b38c6698d95ea06dfd183f38 to your computer and use it in GitHub Desktop.
<cfscript>
// implementation
void function describe(required string label, required function testGroup) {
try {
writeOutput("#label#<br>")
testGroup()
} catch (any e) {
writeOutput("Error: #e.message#<br>")
}
}
void function it(required string label, required function implementation) {
try {
writeOutput("#label#: ")
implementation()
writeOutput("OK<br>")
} catch (TestFailedException e) {
writeOutput("Failed<br>")
} catch (any e) {
writeOutput("Error: #e.message#<br>")
}
}
function expect(required any actual) {
return {toBe = (expected) => {
if (actual.equals(expected)) {
return true
}
throw(type="TestFailedException")
}}
}
</cfscript>
<cfscript>
// tests
// It runs the tests via a function "run"
try {
cfsilent() {
run()
}
writeOutput("OK<br>")
} catch (any e) {
writeOutput("Failure: run function not found #e.message#<br>")
}
void function run(){
// It has a function <samp>describe</samp>
try {
cfsilent(){describe("NOT_TESTED", () => {})}
writeOutput("OK<br>")
} catch (any e) {
writeOutput("Failure: describe function not found<br>")
}
// <samp>describe</samp> takes a string parameter <samp>label</samp> which is displayed on a line by itself as a label for the test grouping
savecontent variable="testOutput" {
describe("TEST_DESCRIPTION", () => {})
};
if (testOutput == "TEST_DESCRIPTION<br>") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: label not output<br>")
}
// <samp>describe</samp> takes a callback parameter <samp>testGroup</samp> which is is executed after the description is displayed
savecontent variable="testOutput" {
describe("TEST_DESCRIPTION", () => {
writeOutput("DESCRIBE_GROUP_OUTPUT")
})
};
if (testOutput == "TEST_DESCRIPTION<br>DESCRIBE_GROUP_OUTPUT") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: testGroup not executed<br>")
}
// <samp>describe</samp> calls can be nested
savecontent variable="testOutput" {
describe("OUTER_TEST_DESCRIPTION", () => {
describe("INNER_TEST_DESCRIPTION", () => {
writeOutput("DESCRIBE_GROUP_OUTPUT")
})
})
};
if (testOutput == "OUTER_TEST_DESCRIPTION<br>INNER_TEST_DESCRIPTION<br>DESCRIBE_GROUP_OUTPUT") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: describe nested did not work<br>")
}
// <samp>describe</samp> will not error-out if an exception occurs in its callback, instead reporting an error result, with the exception's message
savecontent variable="testOutput" {
describe("TEST_DESCRIPTION", () => {
throw "EXCEPTION_MESSAGE";
})
};
if (testOutput CONTAINS "TEST_DESCRIPTION<br>Error: EXCEPTION_MESSAGE<br>") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: the describe function did not correctly report the test error<br>")
}
// The <samp>it</samp> function puts the test result on the same line as the test label, separated by a colon
savecontent variable="testOutput" {
describe("TEST_DESCRIPTION", () => {
it("TEST_CASE_DESCRIPTION", () => {
writeOutput("TEST_CASE_RESULT")
})
})
};
if (testOutput == "TEST_DESCRIPTION<br>TEST_CASE_DESCRIPTION: TEST_CASE_RESULTOK<br>") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: the it function did not work<br>")
}
// <samp>it</samp> will not error-out if an exception occurs in its callback, instead reporting an error result, with the exception's message
savecontent variable="testOutput" {
describe("NOT_TESTED", () => {
it("tests an exception", () => {
throw "EXCEPTION_MESSAGE";
})
})
};
if (testOutput CONTAINS "tests an exception: Error: EXCEPTION_MESSAGE<br>") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: the it function did not correctly report the test error<br>")
}
// <samp>it</samp> outputs OK if the test ran correctly
savecontent variable="testOutput" {
describe("NOT_TESTED", () => {
it("outputs OK if the test ran correctly", () => {
// some test here... this actually starts to demonstrate an issue with the implementation, but we'll get to that
})
})
};
if (testOutput CONTAINS "outputs OK if the test ran correctly: OK<br>") {
writeOutput("OK<br>")
}else{
writeOutput("Failure: the it function did not correctly report the test error<br>")
}
// samp>it</samp> outputs "Failed" if the test failed
savecontent variable="testOutput" {
describe("NOT_TESTED", () => {
it("outputs OK if the test ran correctly", () => {
throw(type="TestFailedException");
})
})
};
if (testOutput.reFind("Failed<br>$") > 0) {
writeOutput("OK<br>")
}else{
writeOutput("Failure: the it function did not correctly report the test failure<br>")
}
it("has a function expect", () => {
expect("NOT_TESTED")
})
it("expect returns a struct with a key toBe which is a function", () => {
var result = expect("NOT_TESTED")
if (isNull(result) || isNull(result.toBe) || !isCustomFunction(local.result.toBe)) {
throw(type="TestFailedException")
}
})
it("toBe returns true if the actual and expected values are equal", () => {
var actual = "TEST_VALUE"
var expected = "TEST_VALUE"
result = expect(actual).toBe(expected)
if (isNull(result) || !result) {
throw(type="TestFailedException")
}
})
it("toBe throws a TestFailedException if the actual and expected values are not equal", () => {
var actual = "ACTUAL_VALUE"
var expected = "EXPECTED_VALUE"
try {
expect(actual).toBe(expected)
} catch (TestFailedException e) {
return
}
throw(type="TestFailedException")
})
var types = ["string", 0, 0.0, true, ["array"], {struct="struct"}, queryNew(""), xmlNew()]
types.each((type) => {
it("works with #type.getClass().getName()#", (type) => {
expect(type).toBe(type)
})
})
}
run()
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment