我正在编写一些旨在在浏览器(客户端,而不是服务器端)中运行的 JavaScript 模块。此模块正在使用 Google Maps JavaScript API .
我想通过单元测试来覆盖我的代码。我还希望隔离我的测试。我找到了 several vcr -喜欢JS libraries用于记录和模拟 Google Maps Api 生成的 HTTP 请求。但它们都是针对 Node.JS 的(因为 PhantomJS doesn't support using fs module )。此外,Node.JS 具有比 PhantomJS 更丰富和可读的回溯。
所以我想知道如何使用基于 Node.JS 的测试运行程序将 Google Maps Javascript API 包含到我的测试中以及如何为我的代码编写测试?
附言我不坚持使用某些特定的 JS 单元测试库。它可以是 Jasmine、QUnit 或任何其他的。
P.P.S 不一定是 Node.JS runner。如果还有其他选择,那完全可以!
P.P.P.S.我的目标是避免以下事情:
P.P.P.P.S.感谢@MichaelGeary answer我们知道 Google 仅保存其 API 的 3 个版本。但我不仅仅关注谷歌地图,我在那个问题中选择它是因为它很受欢迎/我有同样的问题适用于任何其他 map api,如 Yandex.Maps , Leaflet (with openstreet) , Bing等等。他们中的大多数不会删除旧的 API,因此我可以修复版本并依赖于不更改内部 API 和 HTTP 请求。
另外我想避免模拟 hell ,因为我的代码非常复杂并且使用了很多不同种类的地理对象。因此,模拟所有这些然后支持该代码并不容易。这看起来像是无法忍受的事情。
我的想法是在一段时间内修复 API 版本(在 Google 的情况下不会那么长时间)并依赖于内部 HTTP 请求格式的持久性。并时不时地删除所有记录的数据,以确保在现实世界中一切仍然正常。
我希望自己能够控制何时修复我的测试。我不想让 Google 在随机的时间破坏我的测试。
最佳答案
记录或模拟 Maps API 发出的 HTTP 请求这当然是一个有趣的想法!
不幸的是,与 API 的任何其他未记录的功能一样,这些请求是内部实现细节,随时可能更改。谷歌每年推出四次新版本的 API 代码,每隔几周就会发布一次补丁修订。任何 API 内部结构(包括 HTTP 请求)都可能从一个版本更改为下一个版本,即使是在补丁修订中也是如此。他们唯一保证跨版本或补丁稳定的是记录的 API。
Google 确实为您提供了 request a specific API version 的能力,但他们不会将旧版本保留很长时间,而且他们根本不会保留旧补丁修订版。事实上,任何时候只有三个版本在运行。在撰写本文时,这些版本可用:
当推出下一个实验版本(3.22)时,3.21 将成为发布版本,3.20 将成为卡住版本,而 3.19 将退役并不再可用。
卡住版与发布版和实验版有一个区别:它不再接收任何补丁,因此它是完全稳定的。可以安全地假设卡住版本发出的 HTTP 请求不会改变。但这只会在该版本停用之前有所帮助。
这是一个fiddle尝试请求不同的 API 版本并显示实际加载的版本。代码如下所示:
<!DOCTYPE html>
<html>
<head>
<title>Google Maps API version test</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://maps.google.com/maps/api/js?v=3.18&sensor=false"></script>
<div id="version"></div>
<script>
$('#version').text(
'google.maps.version is ' +
google.maps.version
);
</script>
</body>
</html>
fiddle 在 Maps API 脚本 URL 中使用了一个 v=3.18 参数来请求版本 3.18,但此时它实际上加载的是版本 3.19.19。您可以将 v= 参数更改为不同的值,以查看加载了哪个 API 版本。 (除了具体编号的版本,您还可以使用v=3获取当前稳定版本,或使用v=3.exp获取当前实验版本。)
眼尖的读者可能会注意到,此代码显示的 google.maps.version 属性本身是未记录的!但是,嘿,这是实验测试代码。 :-)
HTTP 请求在不同版本之间发生变化是很常见的,甚至可能在补丁修订中发生变化。从上面的列表可以看出,3.19版本经历了19次补丁修改,3.20版本经历了12次补丁修改。
如果您想为 Maps API 代码编写单元测试,我的建议是模拟已记录的 Maps API 本身,而不是模拟其任何内部结构。例如,google.maps.Map 的 mock 可以检查其第一个参数是否为 DOM Node ,以及其第二个(可选)对象参数是否仅包含具有合法值的已知属性。
当然, map API 公开了大量对象、方法和属性,但您不必模拟整个事物,只需模拟您正在使用的部分。
关于javascript - 如何在使用 Google Maps for JS 的代码上编写单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30963596/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h