1. Add and remove a dataset containing information about UBC courses
1. Add and remove a dataset containing information about UBC courses
Courses.zip
addDataset(...)
Parse it
Keep data structure in a variable
Save it to disk
Caching
No need to parse again the same dataset.
No need to go to disk on every request
2. Answer queries about UBC courses.
2. Answer queries about UBC courses.
Examples:
"what departments have courses with averages higher than 90%?"
"What courses in CPSC have a high fail rate?"
2. Answer queries about UBC courses.
{
"WHERE":{
"GT":{
"courses_avg":97
}
},
"OPTIONS":{
"COLUMNS":[
"courses_dept",
"courses_avg"
],
"ORDER":"courses_avg"
}
}
2. Answer queries about UBC courses.
{
"WHERE":{
"GT":{
"courses_avg":97
}
},
"OPTIONS":{
"COLUMNS":[
"courses_dept",
"courses_avg"
],
"ORDER":"courses_avg"
}
}
{ result:
[ { courses_dept: 'epse', courses_avg: 97.09 },
{ courses_dept: 'math', courses_avg: 97.09 },
{ courses_dept: 'math', courses_avg: 97.09 },
{ courses_dept: 'epse', courses_avg: 97.09 },
{ courses_dept: 'math', courses_avg: 97.25 },
{ courses_dept: 'math', courses_avg: 97.25 },
{ courses_dept: 'epse', courses_avg: 97.29 },
{ courses_dept: 'epse', courses_avg: 97.29 },
{ courses_dept: 'nurs', courses_avg: 97.33 },
{ courses_dept: 'nurs', courses_avg: 97.33 } ] }
2. Answer queries about UBC courses. Queries follow the following EBNF:
QUERY ::='{'BODY ', ' OPTIONS '}'
BODY ::= 'WHERE:{' FILTER '}'
OPTIONS ::= 'OPTIONS:{' COLUMNS ', ' ('ORDER:' key )?'}'
FILTER ::= (LOGICCOMPARISON | MCOMPARISON | SCOMPARISON | NEGATION)
LOGICCOMPARISON ::= LOGIC ':[{' FILTER ('}, {' FILTER )* '}]'
MCOMPARISON ::= MCOMPARATOR ':{' key ':' number '}'
SCOMPARISON ::= 'IS:{' key ':' [*]? inputstring [*]? '}'
NEGATION ::= 'NOT :{' FILTER '}'
LOGIC ::= 'AND' | 'OR'
MCOMPARATOR ::= 'LT' | 'GT' | 'EQ'
COLUMNS ::= 'COLUMNS:[' (key ',')* key ']'
key ::= string '_' string
inputstring ::= [^*]+
We previously discussed about software engineering process and methodologies.
We learned about waterfall, spiral, and the many variations of scrum: XP, kanban, and more.
What would be the most adequate methodology to build Insight UBC? How would you approach tests, documentation, design, and development?
Take a few minutes to discuss this with your classmates!
Now that we have a better idea about what methodologies and approaches to use, discuss with your classmates how you would break the deliverable 1 tasks into user stories.
export interface IInsightFacade {
addDataset(id: string,
content: string,
kind: InsightDatasetKind):
Promise<InsightResponse>;
removeDataset(id: string): Promise<InsightResponse>;
performQuery(query: any): Promise<InsightResponse>;
listDatasets(): Promise<InsightResponse>;
}
export interface InsightResponse {
code: number;
body: InsightResponseSuccessBody | InsightResponseErrorBody;
}
export interface InsightResponseSuccessBody {
result: any[] | string;
}
export interface InsightResponseErrorBody {
error: string;
}
export enum InsightDatasetKind {
Courses = "courses",
Rooms = "rooms"
}
export interface InsightDataset {
id: string;
kind: InsightDatasetKind;
numRows: number;
}
it("Test addDataset 204", function () {
let readStream = fs.readFileSync("$PATH_TO_ZIP_FILE").toString('base64');
return facade.addDataset("courses", readStream, InsightDatasetKind.Courses)
.then(function (res: InsightResponse) {
Log.writeResponse(res);
expect(res.code).to.equal(204);
}).catch(function (err: InsightResponse) {
Log.writeResponse(err);
Log.test("Should not have reached this point: " + JSON.stringify(err));
expect.fail();
});
});
it("Test addDataset 204", function () {
let readStream = fs.readFileSync("$PATH_TO_ZIP_FILE").toString('base64');
return facade.addDataset("courses", readStream, InsightDatasetKind.Courses)
.then(function (res: InsightResponse) {
Log.writeResponse(res);
expect(res.code).to.equal(204);
}).catch(function (err: InsightResponse) {
Log.writeResponse(err);
Log.test("Should not have reached this point: " + JSON.stringify(err));
expect.fail();
});
});
base64 string represents the actual zip file
it("Test addDataset 204", function () {
let readStream = fs.readFileSync("$PATH_TO_ZIP_FILE").toString('base64');
return facade.addDataset("courses", readStream, InsightDatasetKind.Courses)
.then(function (res: InsightResponse) {
Log.writeResponse(res);
expect(res.code).to.equal(204);
}).catch(function (err: InsightResponse) {
Log.writeResponse(err);
Log.test("Should not have reached this point: " + JSON.stringify(err));
expect.fail();
});
});
In this unit test we are testing the 204 case, you must test the other cases as well!
it("Test async code", function () {
return facade.asyncFunction(...).then(function (res: InsightResponse) {
expect(res.code).to.equal(<CODE_NUMBER>);
}).catch(function (err: InsightResponse) {
expect.fail();
});
});
Every method from the API returns a promise, it means that every method from the API is an async method. Here's the default template for testing a async function:
it("Test async code", function () {
return facade.asyncFunction(...).then(function (res: InsightResponse) {
expect(res.code).to.equal(<CODE_NUMBER>);
}).catch(function (err: InsightResponse) {
expect.fail();
});
});
More on JS promises and async programming next week
Every method from the API returns a promise, it means that every method from the API is an async method. Here's the default template for testing a async function:
Your local repo/code
Your teammate's local repo/code
Your team GitHub repository
Code in version 0.0
Code in version 0.0
Code in version 0.0
Your local repo/code
Your teammate's local repo/code
Your team GitHub repository
Code in version 0.1
Code in version 0.0
Code in version 0.0
You've changed the code!
Your local repo/code
Your teammate's local repo/code
Your team GitHub repository
Code in version 0.1
Code in version 0.0
Code in version 0.0
git add <PATH_TO_MODIFIED_FILES>
git commit -m "New commit"
Your local repo/code
Your teammate's local repo/code
Your team GitHub repository
Code in version 0.1
Code in version 0.1
Code in version 0.0
git push origin master
Your local repo/code
Your teammate's local repo/code
Your team GitHub repository
Code in version 0.1
Code in version 0.1
Code in version 0.1
git pull origin master
git checkout -b branch_name
Creating and moving to a new local branch
Pushing the new local branch to GitHub
git add <path_to_modified_files>
git commit -m "Message"
git push origin branch_name
git checkout -b branch_name
Creating and moving to a new local branch
Pushing the new local branch to GitHub
git add <path_to_modified_files>
git commit -m "Message"
git push origin branch_name
Merging to master branch
git checkout master
git merge branch_name
TDD and testing can help you break down the high level goals -- addDataset(), performQuery() -- into smaller, easily testable tasks: saveDatasetToDisk(), validateQuery().
Write these tests first, make sure they fail, then write the code to make them pass