如何在 PC 上本地测试 Cloud Functions for Firebase

Posted

技术标签:

【中文标题】如何在 PC 上本地测试 Cloud Functions for Firebase【英文标题】:how to test Cloud Functions for Firebase locally on pc 【发布时间】:2017-08-01 06:23:09 【问题描述】:

今天 Firebase 发布了它的全新产品 Cloud Functions for Firebase,我刚刚创建了一个 hello world 函数并将其部署到我现有的 firebase 项目中。

它看起来就像 aws lambda function 一样捆绑了所有依赖项并将其上传到 firebase。但是即使代码的微小变化也需要花费太多时间,并且还需要良好的互联网连接。如果您由于某种原因处于离线状态,那么在您有办法在本地计算机上离线执行和测试该功能之前,您只是不知道您正在编写什么代码。

有什么方法可以在本地测试 Cloud Functions for Firebase?

【问题讨论】:

【参考方案1】:

firebaser 在这里

部署您的函数确实比我通常愿意等待的时间要长。我们正在努力改进这一点,并且(正如 Brendan 所说)正在开发本地模拟器。

但目前,我主要是先将我的实际业务逻辑写入一个单独的 Node 脚本。这样我就可以在本地命令提示符下使用node speech.js 对其进行测试。一旦我对函数的工作感到满意,我要么将其复制/粘贴到我的实际函数文件中,要么(更好)将speech 模块导入我的函数文件并从那里调用它。

我很快找到的一个简短示例是我使用 Cloud Vision API 连接文本提取时。我有一个名为 ocr.js 的文件,其中包含:

var fetch = require('node-fetch');

function extract_text(url, gcloud_authorization) 
  console.log('extract_text from image '+url+' with authorization '+gcloud_authorization);

  return fetch(url).then(function(res) 
    return res.buffer();
  ).then(function(buffer) 
    return fetch('https://vision.googleapis.com/v1/images:annotate?key='+gcloud_authorization, 
      method: "POST",
      headers: 
        "Content-Type": "application/json"
      ,
      body: JSON.stringify(
        "requests":[
          
            "image":
              "content": buffer.toString('base64')
            ,
            "features":[
              
                "type":"TEXT_DETECTION",
                "maxResults":1
              
            ]
          
        ]
      )
    );
  ).then(function(res) 
    var json = res.json();
    if (res.status >= 200 && res.status < 300) 
      return json;
     else 
      return json.then(Promise.reject.bind(Promise));
    
  ).then(function(json) 
    if (json.responses && json.responses.length && json.responses[0].error) 
      return Promise.reject(json.responses[0].error);
    
    return json.responses[0].textAnnotations[0].description;
  );


if (process.argv.length > 2) 
  // by passing the image URL and gcloud access token, you can test this module
  process.argv.forEach(a => console.log(a));
  extract_text(
    process.argv[2], // image URL
    process.argv[3]  // gcloud access token or API key
  ).then(function(description) 
    console.log(description);
  ).catch(function(error) 
    console.error(error);
  );


exports.extract_text = extract_text;

然后在我的 Functions index.js 中,我有:

var functions = require('firebase-functions');
var fetch = require('node-fetch');
var ocr = require('./ocr.js');

exports.ocr = functions.database().path('/messages/room/id').onWrite(function(event) 
  console.log('OCR triggered for /messages/'+event.params.room+'/'+event.params.id);

  if (!event.data || !event.data.exists()) return;
  if (event.data.ocr) return;
  if (event.data.val().text.indexOf("https://firebasestorage.googleapis.com/") !== 0) return; // only OCR images

  console.log(JSON.stringify(functions.env));

  return ocr.extract_text(event.data.val().text, functions.env.googlecloud.apikey).then(function(text) 
    return event.data.adminRef.update( ocr: text );
  );
);

如您所见,最后一个文件实际上只是将“工作方法”ocr.extract_text 连接到数据库位置。

请注意,这是不久前的一个项目,因此某些语法(主要是 functions.env 部分)可能有所改变。

【讨论】:

您能否分享任何实际示例,或至少参考包含您在回答中描述的 hello world program 的任何存储库 测试在实践中是如何工作的?你提到你在命令行运行node speech.js。但这不测试你程序的操作逻辑是否正确?它只测试我猜的“设置”(即语法、依赖项等)?如果正确,有没有办法在本地测试操作逻辑? 我从命令行传入 GCP 需要的值。所以它测试我的脚本及其与外部 API 的交互。如果数据进入 Cloud Functions,它不会测试实际流量。【参考方案2】:

firebaser 在这里

要在本地调试 Cloud Functions for Firebase,有一个模拟器。请参阅documentation for more info。

【讨论】:

Alpha 版 Firebase 模拟器可用于 https 功能:firebase.google.com/docs/functions/local-emulator @BrianLenoski 似乎调试选项不见了?您提供的链接显示了如何在本地运行,而不是如何调试。【参考方案3】:

在本地运行和调试/检查函数

先决条件(google-cloud 功能和特定于 firebase):

npm install -g @google-cloud/functions-emulator
npm install --save firebase-functions
npm install -g firebase-tools

运行和检查/调试:首先在本地运行函数,然后检查每个函数,最后运行每个特定函数以调试+检查它。使用functions start 替代firebase serve,并注意每个工具的文档都可用(且有用)。

按预期运行和调试特定功能myFn(例如in Nodejs 通过chrome://inspect 并注意这可以使用Nodejs v10,但不受官方支持):

firebase serve --only functions
functions inspect myFn
functions call myFn # or call from browser

其他文档:

https://firebase.google.com/docs/functions/local-emulator https://cloud.google.com/functions/docs/emulator#debug-emulator https://github.com/GoogleCloudPlatform/cloud-functions-emulator/wiki

【讨论】:

可以做单步吗?允许检查变量的值吗? 我收到Error: FIREBASE FATAL ERROR: Cannot parse Firebase url. Please use https://&lt;YOUR FIREBASE&gt;.firebaseio.com【参考方案4】:

>> 有什么方法可以在本地测试 Cloud Functions for Firebase?

您可以使用以下命令启动 firebase shell(在您的函数目录中执行):

npm run build && firebase functions:shell

你可以像这样在 shell 中调用你的函数:

helloWorld()

请参阅this 链接了解更多信息。

【讨论】:

【参考方案5】:

在这里回答:https://github.com/firebase/firebase-functions/issues/4#issuecomment-286515989

Google Cloud Functions 还开源了一个本地模拟器,我们正在 致力于与 Cloud Functions 建立更紧密的集成 火力基地。同时,您可以在这里查看: https://github.com/GoogleCloudPlatform/cloud-functions-emulator/

模拟器允许您在本地运行函数。这是 解释如何使用它的文档: https://cloud.google.com/functions/docs/emulator

【讨论】:

【参考方案6】:

一开始我无法让单步执行。我的过程与此处许多答案中记录的过程相同。

此外,这些页面几乎包含我需要的所有文档:

https://firebase.google.com/docs/functions/local-emulator https://cloud.google.com/functions/docs/emulator#debugging_with_the_emulator

我已经使用firebase serve --only functions 运行了函数,但还没有启动并运行调试器。然后我遇到了直接使用模拟器的另一种方式,并设法达到了这样的断点:

# start the emulator
functions start

# allow inspection
functions inspect helloWorld

# call the function from the cli
functions call helloWorld

这行得通,我可以打断点。

但是,当在邮递员或浏览器中点击函数的端点时,我根本没有得到任何响应。

我缺少的步骤是:

# deploy the function to the emulator
functions deploy helloWorld --trigger-http

# you need to toggle inspection after the deploy
functions inspect helloWorld

现在我可以从邮递员或浏览器中命中函数的端点,并命中断点。

我推荐出色的 NiM chrome extension 进行调试,并希望这个答案对某人有所帮助,即使这是一个老问题。

【讨论】:

【参考方案7】:

首先,我建议你安装以下依赖项,

npm install --save firebase-functions
npm install -g firebase-tools 

如果已经安装,那么您可以将其更新到最新版本。一般来说,functions-emulator 都有上述依赖,但我还是建议你更新它,

npm install -g @google-cloud/functions-emulator

更新后,进入应用程序的functions文件夹并运行以下命令,

firebase serve --only functions

希望对你有帮助!

【讨论】:

【参考方案8】:

适用于调试 HTTP 函数(webhooks 等)的 vscode 用户...

谷歌云模拟器 (firebase serve --only functions) 会启动一个单独的进程来运行您的函数。您可以使用 vscode 附加到此进程,但由于模拟器仅在调用第一个函数之后创建此进程,因此并不简单。

在您的函数中创建一个虚拟 HTTP 端点,该端点将返回 processID:
app.get("/processid", function(request, response) 
  response.send(`$process.pid`);
);
firebase serve --only functions启动模拟器 调用http://&lt;localhost_url&gt;/processid 端点。这将创建进程并返回 processID 使用 vscode 附加到指定进程。您现在可以在任何其他函数上设置断点、步骤等(它们都使用相同的过程)。

可能有更好的方法将所有这些粘合在一起。

【讨论】:

我发现在 index.js 的顶部记录 process.pid 更容易。它会针对每个新进程进行评估,并且会在您运行“firebase serve”后立即发生 - 无需发出请求即可获得它。 @Tom 除了这似乎不起作用。正如我所提到的,当调用第一个函数时会启动一个新进程。您可以通过查看 index.js 顶部记录的进程 ID 与 /processid 函数调用返回的进程 ID 不同来验证这一点。 哦,这很奇怪。我很确定它对我有用。我会在下次处理该问题时重新检查 - 也许它的行为在这方面不一致。 感谢@adelphus,这正是我一直在寻找的东西,很好。 如何附加到进程?【参考方案9】:

现在有一个云functions emulator that 可以让你在本地调用函数

完成 PoC 后,我将更新此答案以包含我使用的代码和步骤。

【讨论】:

以上是关于如何在 PC 上本地测试 Cloud Functions for Firebase的主要内容,如果未能解决你的问题,请参考以下文章

在本地测试 Python Google Cloud Functions

如何将消息从 GCP 推送订阅传递到本地 PC?

如何将 Google Cloud Firestore 本地模拟器用于 python 和测试目的

在本地测试 Cloud Functions 时,Cloud Firestore 模拟器未运行

如何在我的本地 linux 服务器上运行 google-cloud-datalab?

如何将数据从 Cloud Firestore 导入到本地模拟器?