deno_std
deno_std copied to clipboard
bdd testing: easy testing of arrays
Is your feature request related to a problem? Please describe.
Yes. currently, it's not very easy to test arrays of data. For example, I'm writing a library that parses (rather complex) musical data into reusable JSON structures.
Take this example:
const data = get_data() as Data;
interface Data {
title: string;
categories: {
title: string;
results: (Playlist | Song | Album | Artist | ...)[];
};
}
this is how I'm testing this currently
describe("data", () => {
let data: Data;
beforeAll(async () => {
data = await get_data();
})
it("title", () => {
assertEquals(typeof title, "string");
});
describe("categories", () => {
it("present", () => {
assert(data.categories.length > 0);
});
describe("category", () => {
let category: any;
beforeAll(() => {
category = data.categories[0];
});
it("name", () => {
assert(category.name.length > 0);
});
it("params", () => {
assert(category.params.length > 0);
});
// I'm not even testing `category.results`, it's too complex
})
})
});
Describe the solution you'd like
It would be nice if for example the describe
function could take in arrays I'm not sure (or an iterator).
describe("category", () => {
let category: any;
let id = 0;
// Notice this is a generator function
// this would be run each time unless it doesnt yield something
beforeAll(* () => {
while (true) {
if (id >= data.categories.length) {
break;
}
yield category = data.categories[id++];
}
});
it("name", () => {
assert(category.name.length > 0);
});
it("params", () => {
assert(category.params.length > 0);
});
})
or maybe something attached to describe
describe(
"category",
forEach = (id: number) => {
this.category = data.categories[id];
return id < data.categories.length;
},
fn() {
it("name", function (this: { category: any }) => {
assert(this.category.name.length > 0);
});
it("params", function (this: { category: any }) {
assert(this.category.params.length > 0);
});
},
);
Describe alternatives you've considered
I've tried many alternatives, but no one really worked. right now I'm just using asserts (hence throwing away the benefits of bdd
data.categories.forEach((category) => {
assertEqual(typeof category, "string");
// etc...
)
You can call it or describe in a for loop or a forEach block. Here is an example based on code samples you provided. In it, it will register a test group for each category with names in the format category[0]
, but you could construct the names to be whatever you want, even using variables from the category object. Then for each category, it would register 2 test steps, one for name and one for params.
data.categories.forEach((category, index) => {
describe(`category[${index}]`, () => {
it("name", () => {
assert(category.name.length > 0);
});
it("params", () => {
assert(category.params.length > 0);
});
});
});
If you have tests you only want to run for specific types of category objects, you could use if blocks to conditionally register different types of tests. And it doesn't all have to be in a single for loop or forEach, you could create functions for registering sets of tests then conditionally call them.
The describe/it function's are pretty flexible. I would personally prefer not adding something like the 2 examples provided. I believe it would make it more confusing to read and write test cases. In your first example, one might miss that there is a generator in their beforeAll when reading the test cases. For both examples, I'd have another question, which is what would the names for each of those cases generated? With the example I wrote, I believe it's much more clear how the test cases are being registered and what the names will be.
I can't do data.categories.forEach
because data
itself is loaded in a beforeAll
.
I haven't found a way to load data
directly so this can't work.