如何在GAS中测试触发功能?

Mog*_*dad 43 google-sheets google-apps-script

Google Apps脚本支持触发器,可将事件传递给触发器功能.不幸的是,开发环境将允许您在没有参数传递的情况下测试函数,因此您无法以这种方式模拟事件.如果你尝试,你会收到如下错误:

ReferenceError:未定义'e'.

可以将事件视为可选参数,并使用" 在JavaScript中有更好的方法来执行可选函数参数吗? "中的任何技术将默认值插入到触发器函数中.但是这会带来一种风险,即一个懒惰的程序员(如果那就是你那么举手!)会留下那些代码,带来意想不到的副作用.

当然还有更好的方法吗?

Mog*_*dad 73

您可以编写一个测试函数,将模拟事件传递给触发器函数.这是一个测试onEdit()触发器功能的示例.它传递一个事件对象,其中包含在了解事件中为"电子表格编辑事件"描述的所有信息.

要使用它,请在目标onEdit函数中设置断点,选择函数test_onEdit并点击Debug.

/**
 * Test function for onEdit. Passes an event object to simulate an edit to
 * a cell in a spreadsheet.
 *
 * Check for updates: https://stackoverflow.com/a/16089067/1677912
 *
 * See https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
 */
function test_onEdit() {
  onEdit({
    user : Session.getActiveUser().getEmail(),
    source : SpreadsheetApp.getActiveSpreadsheet(),
    range : SpreadsheetApp.getActiveSpreadsheet().getActiveCell(),
    value : SpreadsheetApp.getActiveSpreadsheet().getActiveCell().getValue(),
    authMode : "LIMITED"
  });
}
Run Code Online (Sandbox Code Playgroud)

如果你很好奇,这是为了测试Google SpreadsheetonEdit功能,条件是三个单元格.

这是电子表格表单提交事件的测试功能.它通过读取表单提交数据来构建其模拟事件.这最初是为onFormSubmit触发器中的Get TypeError编写的.

/**
 * Test function for Spreadsheet Form Submit trigger functions.
 * Loops through content of sheet, creating simulated Form Submit Events.
 *
 * Check for updates: https://stackoverflow.com/a/16089067/1677912
 *
 * See https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
 */
function test_onFormSubmit() {
  var dataRange = SpreadsheetApp.getActiveSheet().getDataRange();
  var data = dataRange.getValues();
  var headers = data[0];
  // Start at row 1, skipping headers in row 0
  for (var row=1; row < data.length; row++) {
    var e = {};
    e.values = data[row].filter(Boolean);  // filter: https://stackoverflow.com/a/19888749
    e.range = dataRange.offset(row,0,1,data[0].length);
    e.namedValues = {};
    // Loop through headers to create namedValues object
    // NOTE: all namedValues are arrays.
    for (var col=0; col<headers.length; col++) {
      e.namedValues[headers[col]] = [data[row][col]];
    }
    // Pass the simulated event to onFormSubmit
    onFormSubmit(e);
  }
}
Run Code Online (Sandbox Code Playgroud)

提示

在模拟事件时,请注意尽可能地匹配记录的事件对象.

  • 如果要验证文档,可以从触发器功能中记录接收的事件.

    Logger.log( JSON.stringify( e , null, 2 ) );
    
    Run Code Online (Sandbox Code Playgroud)
  • 在电子表格表单提交事件中:

    • 所有namedValues值都是数组.
    • 时间戳是字符串,它们的格式将本地化为表单的区域设置.如果从具有默认格式*的电子表格中读取,则它们是Date对象.如果您的触发器函数依赖于时间戳的字符串格式(这是一个坏主意),请注意确保您正确地模拟该值.
    • 如果您的电子表格中的列不在您的表单中,则此脚本中的技术将模拟包含这些附加值的"事件",这不是您从表单提交中获得的内容.
    • 问题4335所述,values数组跳过空白答案(在"新表格"+"新表格"中).该filter(Boolean)方法用于模拟此行为.

*格式化为"纯文本"的单元格将日期保留为字符串,并不是一个好主意.

  • test_onEdit,当从 GScript IDE 运行/调试时,给出错误:“请首先选择一个活动工作表”。我尝试打开电子表格并在 test_onEdit 中设置活动工作表,但同样的错误在调用 onEdit 时停止执行。我是否错过了初步步骤? (2认同)

The*_*ter 8

2020 年更新:

您不需要使用前面答案中建议的任何类型的模拟事件。

正如问题中所说,如果您直接在脚本编辑器中“运行”该函数,则会出现类似错误

类型错误:无法读取属性...来自未定义

被抛出。这些都不是真正的错误。此错误只是因为您在没有事件的情况下运行了该函数。如果您的函数没有按预期运行,您需要找出实际错误:

要测试触发功能,

  1. 手动触发相应事件:即 To test onEdit,编辑sheet中的一个单元格;要测试onFormSubmit,请提交一个虚拟表单响应。要进行测试doGet,请将浏览器导航到已发布的 webapp /execurl。

  2. 如果有任何错误,则会记录到 stackdriver。要查看这些日志,

    • 在脚本编辑器 > 查看 > 执行中。

    • 或者,单击此处> 单击您感兴趣的项目 > 在“项目详细信息”仪表板中 > 单击右上角的三点菜单 > 单击“执行”

  3. 您将在执行页面中找到执行列表。确保清除左上角的任何过滤器,如“Ran as:Me”以显示所有执行。单击您感兴趣的执行,它将以红色显示导致触发器失败的错误。

注意:有时,由于错误,日志不可见。这是真的,尤其是在匿名用户运行 webapp 的情况下。在这种情况下,建议将默认谷歌云项目切换为标准谷歌云项目,并直接使用查看> Stackdriver 日志记录。请参阅此处了解更多信息。

  1. 为了进一步调试,您可以使用编辑代码console.log(/*object you're interested in*/)在您感兴趣的任何行之后添加以查看该对象的详细信息。这是强烈建议你字符串化你要找的对象:console.log(JSON.stringify(e))作为日志查看器具有的特质。添加后console.log(),从第 1 步开始重复。重复此循环,直到缩小问题范围。

恭喜!您已经成功地解决了问题并克服了第一个障碍。


ran*_*rts 6

2017更新:使用Stackdriver Logging for Google Apps Script 调试Event对象.从脚本编辑器的菜单栏中,转到: 查看或流式传输日志.View > Stackdriver Logging

console.log()将编写DEBUG级别消息

示例onEdit():

function onEdit (e) {
  var debug_e = {
    authMode:  e.authMode,  
    range:  e.range.getA1Notation(),    
    source:  e.source.getId(),
    user:  e.user,   
    value:  e.value,
    oldValue: e. oldValue
  }

  console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}
Run Code Online (Sandbox Code Playgroud)

示例onFormSubmit():

function onFormSubmit (e) {
  var debug_e = {
    authMode:  e.authMode,  
    namedValues: e.namedValues,
    range:  e.range.getA1Notation(),
    value:  e.value
  }

  console.log({message: 'onFormSubmit() Event Object', eventObject: debug_e});
}
Run Code Online (Sandbox Code Playgroud)

示例onChange():

function onChange (e) {
  var debug_e = {
    authMode:  e.authMode,  
    changeType: changeType,
    user:  e.user
  }

  console.log({message: 'onChange() Event Object', eventObject: debug_e});
}
Run Code Online (Sandbox Code Playgroud)

然后检查Stackdriver UI中标记为message字符串的日志以查看输出