В Google Apps Script я тестирую юнит-приложение, над которым я работаю, , используя QUnit , используя тестируемую разработку.
Кодпод тестом
Сейчас я работаю над полным тестированием, а затем разрабатываю следующую функцию:
/**
*
* Creates a Sheet from a long string of data
* @param { string } data : the long string of data
* @returns { Sheet } the newly-created Sheet
**/
function createSheetFrom(data) {
// if data is not in the form of a string, we've got a problem
if (data !== data.toString())
throw TypeError("Data must be in the form of a string")
// parse the data into SheetData
sheetData = SheetData.parse(data);
// create a new Sheet
newSheet = SPREADSHEET.insertSheet(sheetData.projectName)
// create title rows for it
createTitleRow(sheet)
return newSheet
}
, где SPREADSHEET
- сценарий Spreadsheet
прикреплен, сохранен как глобальная переменная для удобства.
Эта функция зависит, среди прочего, от той, которая находится прямо под ней, которая была успешно полностью протестирована и разработана:
/**
* Creates a title row for the spreadsheet
*
* @param { Sheet } sheet : the spreadsheet to create a title row for
* @returns { Sheet } the sheet for chaining purposes
**/
function createTitleRow(sheet) {
// declare the titles
var titles = ["File", "Total Cyclomatic Complexity", "Already unit-tested?", "Status Date"];
// insert a row right at the beginning
sheet.insertRows(1);
var titleRow = sheet.getRange(1, 1, 1, titles.length);
// set some values on titleRow
titleRow.setValues(titles);
titleRow.setHorizontalAlignment(CENTER)
return sheet;
}
Тесты:
Мой тест против createSheetFrom выглядит следующим образом:
function testCreateSheetFrom() {
var globalSpreadsheet // for storing the state of SPREADSHEET
var sheet // a stub Sheet
var createTitleRowCalls = []
var titleRowFunction
QUnit.test("testing createSheetFrom with 'file contents' that is simply one line of output",
function() {
throws(function() {
val = createSheetFrom("3 blah funcName c:/blah/foo/bar");
}, "Exception caught successfully")
})
}
... и тест против createTitleRow:
function testCreateTitleRow() {
var sheet // spy for the Sheet object from the Google Spreadsheet API
QUnit.testStart(function() {
// create a sheet spy
sheet = {
insertRowsCalls : [],
insertRows : function(idx) {
Logger.log("insertRows called")
this.insertRowsCalls.push({ args : idx });
},
getRangeCalls : [],
range : {
setValuesCalls : [],
setValues : function(arr) {
if (!Array.isArray(arr)) return;
// simply record the args that this was called with
this.setValuesCalls.push({ args : arr });
},
setHorizontalAlignment: function(setting) {}
},
// method stub
getRange : function(r0,c0,r1,c1) {
Logger.log('getRange called')
this.getRangeCalls.push({ args : Array.prototype.splice.call(arguments, 0) });
return this.range;
}
};
})
QUnit.test("testing createTitleRow",
function() {
// hit the method under test
val = createTitleRow(sheet);
// the methods better have been hit
equal(sheet.insertRowsCalls.length, 1, "sheet.insertRows only got invoked once")
ok(sheet.getRangeCalls, "sheet.getRange() got invoked at least once")
ok(sheet.getRangeCalls.length)
deepEqual(sheet.getRangeCalls[0].args.filter(function(val, key) { return key < 3 }), [1,1,1], "the right arguments got sent to sheet.getRange()")
setValuesCalls = sheet.range.setValuesCalls
ok(setValuesCalls.length, "A call was made to sheet.range.setValues")
equal(setValuesCalls[0].args.length, 4, "The call was made with four args, as we expect")
// sheet better have been returned
equal(val, sheet, "createTitleRow() returns the sheet for testing, as promised")
})
}
Все тесты проходят:
Тем не менее, когда я добавляю к тестам против createSheetFrom
следующий тест на работоспособность, заглушая createTitleRow
в настройке, возвращая его обратно к реальному самомув разрыве оба теста против createSheetFrom
и createTitleRow
break!
Код для этого теста на разрыв:
QUnit.testStart(function() {
// create a spy out of sheet
sheet = {
}
// replace SPREADSHEET with a spy
globalSpreadsheet = SPREADSHEET
SPREADSHEET = {
insertSheetCalls : [],
insertSheet : function(str) {
this.insertSheetCalls.push({ args: str })
return sheet
}
}
// stub out the dependencies
titleRowFunction = createTitleRow
createTitleRow = function(sheet) {
createTitleRowCalls.push({ args : sheet })
return sheet
}
})
QUnit.test("SanityTesting createSheetFrom",
function() {
projectName = "main"
complexity = 3
packageName = "main"
funcName = "SetContext"
filename = "main.go"
fileContents = createFileContents(projectName,
createLineOfTextFrom(complexity, packageName, funcName, "C:/Users/mwarren/Desktop/" + filename))
sheet = createSheetFrom(fileContents)
ok(SPREADSHEET.insertSheetCalls.length, "SPREADSHEET.insertSheet got called")
})
QUnit.testDone(function() {
// set SPREADSHEET back
SPREADSHEET = globalSpreadsheet
// set the dependencies back
createTitleRow = titleRowFunction
})
Скриншоты тестовых регрессий:
Я не знаю, почему происходят эти регрессии, тем более, что я откладываю изменения, которые я внес в настройку ...
Состояния используемых объектов переносятся в другие тестовые случаи в других тестовых функциях, несмотря на то, что я использовал testDone
для установки состоянийобъектов назад.Теперь это происходит и в других тестовых примерах