在 Google Apps 脚本中,我正在对我正在开发的应用程序进行单元测试,使用 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
的测试都失败了!
该破坏测试的代码:
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
来设置对象的状态,但所使用的对象的状态仍会转移到其他测试函数中的其他测试用例。现在其他测试用例中也发生了这种情况
GitHub 上的库存储库在 2020 年发布了以下未解决问题:
GAS Qunit 无法在新的 V8 Apps 脚本引擎中工作
它包括指向 Google Apps 脚本的其他 QUnit 库的注释:
来自 https://github.com/simula-innovation/qunit/issues/5#issuecomment-667643668:
查看 QUnitGS2 - 使用最新版本 QUnit (v2.10.1) 的新 Apps 脚本库。
来自 https://github.com/simula-innovation/qunit/issues/5#issuecomment-749455762