﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-RTY 实践出真知-随笔分类-质量保障</title><link>http://www.cppblog.com/lauer3912/category/17748.html</link><description>没有理由不学习</description><language>zh-cn</language><lastBuildDate>Sat, 19 Jul 2014 15:01:43 GMT</lastBuildDate><pubDate>Sat, 19 Jul 2014 15:01:43 GMT</pubDate><ttl>60</ttl><item><title>Google Breakpad 完全解析（二） —— Windows前台实现篇</title><link>http://www.cppblog.com/lauer3912/archive/2011/11/07/159785.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 07 Nov 2011 13:36:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/11/07/159785.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/159785.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/11/07/159785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/159785.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/159785.html</trackback:ping><description><![CDATA[<div><h2>Google Breakpad 完全解析（二） &#8212;&#8212; Windows前台实现篇</h2> 2011年02月7日 &#8212; Asp J   <div><h3>Table of contents for Google Breakpad 完全解析</h3><ol><li><a href="http://bigasp.com/archives/450" title="Google Breakpad 完全解析（一） &#8212;&#8212; Windows入门篇">Google Breakpad 完全解析（一） &#8212;&#8212; Windows入门篇</a></li><li>Google Breakpad 完全解析（二） &#8212;&#8212; Windows前台实现篇</li></ol></div> <p>原创文章，转载请标明出处：Soul Apogee (<a href="http://bigasp.com/" target="_blank">http://bigasp.com</a>)，谢谢。</p> <p>好，看完了<a href="http://bigasp.com/archives/450" target="_blank">如何使用breakpad</a>，我们现在看看breakpad在Windows下到底是如何实现的呢？</p> <h3><strong>代码结构</strong></h3> <p>在我们来看breakpad是如何实现其强大的功能之前，我们先来看一下他的代码结构吧。</p> <p>Google breakpad的源代码都在src的目录下，他分为如下几个文件夹：<br /> client：这下面包含了前台应用程序中捕捉dump的部分代码，里面按照平台分成各个子文件夹<br /> common：前台后台都会用到的部分基础代码，字符串转换，内存读写，md5神马的<br /> google_breakpad：breakpad中公共的头文件<br /> processor：用于在后台处理崩溃的核心代码<br /> testing：测试工程<br /> third_party：第三方库<br /> tools：一些小工具，用于处理dump文件和符号表</p> <p>我们先来看Windows下前台实现的部分，也就是client文件夹下的代码。</p> <h3><strong>breakpad的崩溃捕获机制</strong></h3> <p>在Windows下捕获崩溃，大家很容易会想到那个捕获结构化异常的Api：<a target="blank" href="http://www.google.com/search?ie=UTF-8&amp;q=SetUnhandledExceptionFilter">SetUnhandledExceptionFilter</a>。</p> <p>breakpad中也使用了这个Api来实现的崩溃捕获，另外，breakpad还捕获了另外两种C++运行库提供的崩溃，一种是使用<a target="blank" href="http://www.google.com/search?ie=UTF-8&amp;q=_set_purecall_handler">_set_purecall_handler</a>捕获纯虚函数调用产生的崩溃，还有一种是使用<a target="blank" href="http://www.google.com/search?ie=UTF-8&amp;q=_set_invalid_parameter_handler">_set_invalid_parameter_handler</a>捕获错误的参数调用产生的崩溃。</p> <div><div id="highlighter_32943"  cpp"=""><div><a href="http://bigasp.com/archives/458#" command_help=""  help"="">?</a></div><table cellpadding="0" cellspacing="0" border="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div></td><td><div><div number1="" index0=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code> <code plain"="">(handler_types &amp; HANDLER_EXCEPTION)</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">previous_filter_ = SetUnhandledExceptionFilter(HandleException);</code></div><div number3="" index2=""  alt2"="">&nbsp;</div><div number4="" index3=""  alt1"=""><code preprocessor"="">#if _MSC_VER &gt;= 1400&nbsp;&nbsp;// MSVC 2005/8</code></div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code> <code plain"="">(handler_types &amp; HANDLER_INVALID_PARAMETER)</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);</code></div><div number7="" index6=""  alt2"=""><code preprocessor"="">#endif&nbsp;&nbsp;// _MSC_VER &gt;= 1400</code></div><div number8="" index7=""  alt1"="">&nbsp;</div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code> <code plain"="">(handler_types &amp; HANDLER_PURECALL)</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">previous_pch_ = _set_purecall_handler(HandlePureVirtualCall);</code></div></div></td></tr></tbody></table></div></div> <p>另外由于C++运行库提供的崩溃回调中，并不会提供当前的线程现场和崩溃信息，所以breakpad会自己生成好这些信息，然后请求生成dump。<br /> 这里值得一说的是，在非异常崩溃处理中，breakpad获取线程现场使用的函数是RtlCaptureContext而不是GetThreadContext。<br /> RtlCaptureContext只能捕获当前线程的现场，而GetThreadContext可以捕获任意线程的现场，只要有这个线程的句柄即可。<br /> 但是GetThreadContext有两个不好的地方：不能获取当前线程的现场；获取现场前必须先用SuspendThread暂停目标线程。<br /> 而RtlCaptureContext虽然只能获取当前线程的现场，但是调用他时可以不用暂停线程的运行。<br /> 对于breakpad来说，崩溃发生后越早获取现场就越好，所以breakpad使用RtlCaptureContext函数作为他的线程获取函数。</p> <h3><strong>breakpad中的C/S结构</strong></h3> <p>由于breakpad是在进程外抓取dump，所以breakpad需要实现一个C/S结构来处理崩溃进程抓取dump的请求。</p> <p><strong>1. breakpad跨进程通信的实现<br /> </strong>breakpad中使用了命名管道来实现IPC。</p> <p>在客户端，初始化ExceptionHandler的时候，如果指定了PipeName，也就表示此时需要使用进程外的dump抓 取，ExceptionHandler，会建立一个&nbsp;CrashGenerationClient的对象，由这个对象连接服务端，将自己注册到服务端上 去。<br /> 大家可以参看exception_handler.cc中的ExceptionHandler::Initialize函数。</p> <p>在服务端，初始化CrashGenerationServer的时候，就会建立一个命名管道，并等待客户端来连接。一旦有客户端连接上来，服务端会 为每一个客户端生成一个ClientInfo的对象，之后用这个对象来管理所有的客户端，一旦有崩溃发生，服务端都会从这个对象中取出dump所需要的信 息。<br /> 大家可以参看crash_generation_server.cc中的CrashGenerationServer::HandleReadDoneState函数。</p> <p><strong>2. breakpad捕获崩溃生成dump的流程<br /> </strong>breakpad进程外生成dump的流程大概如下：<br /> <strong>google-breakpad-out-of-process-dump:</strong><br /><a href="http://bigasp.com/wp-content/plugins/download-monitor/download.php?id=138" target="_blank"><img src="http://bigasp.com/wp-content/uploads/downloads/thumbnails/2011/02/google-breakpad-out-of-process-dump.jpg" alt="google-breakpad-out-of-process-dump" style="max-width:500px;" /></a><br /> 这段流程的代码就是crash_generation_client.cc和crash_generation_server.cc。</p> <p>有两个简单的问题，这里说明一下，高手们就请直接忽略吧，咩哈哈：<br /> <strong>在服务端如何为客户端生成事件句柄？</strong><br /> 使用DuplicateHandle，即可把任意一个内核对象的句柄复制到其他进程，并且可以指定产生的句柄的权限。</p> <p><strong>如何异步的等待一个事件？<br /> </strong>使用RegisterWaitForSingleObject，即可异步的等待一个事件，当事件发生的时候，就可以回调到一个指定的回 调函数中，但是要注意的是，RegisterWaitForSingleObject会在一个新的线程中来等待这个事件，此处很容易产生多线程的调用，需 要注意线程问题。</p> <p><strong>3. 服务端关键数据结构：ClientInfo<br /> </strong>ClientInfo是服务端中最重要的数据结构，服务端通过它来管理所有的客户端。客户端注册时，会保存或生成里面所有的信息，在客户端请求生成dump的时候，服务端就会通过ClientInfo获取所有客户端的信息。ClientInfo中保存了如下信息：</p> <ul><li>客户端进程pid和句柄</li><li>生成Minidump的类型</li><li>自定义的客户端信息</li><li>客户端崩溃的线程ID</li><li>客户端崩溃的信息</li><li>客户端请求崩溃所使用的事件句柄</li></ul> <p>这里有一个问题：在客户端发生崩溃时，服务器如何通过ClientInfo获取到客户端的崩溃信息呢？</p> <p>客户端中有几个用于保存崩溃信息的变量，在注册时，客户端会将这几个变量的地址发送至服务端，服务端将其保存在ClientInfo中，然后当崩溃 发生的时候，服务端就可以通过ReadProcessMemory读取客户端中的信息，从而生成dump。这样做就避免了每次发生崩溃，都要通过Pipe 将崩溃信息传递到服务端中去了。</p> <p>这些变量分别是：崩溃的线程ID，EXCEPTION_POINTERS和MDRawAssertionInfo。<br /> EXCEPTION_POINTERS和MDRawAssertionInfo的区别在于，异常崩溃的信息会被写入EXCEPTION_POINTERS，非异常崩溃（非法参数和纯虚函数调用）的信息会被写入MDRawAssertionInfo中。</p> <h3><strong>dump文件的上传</strong></h3> <p>在breakpad的工程中，有一个工程叫做：crash_report_sender，里面是一个上传崩溃文件的类，他的实现很简单，他使用Windows Internet Api来完成dump文件的上传。<br /> 在使用crash_report_sender时，可以为其指定一个checkpoint_file。</p> <div><div id="highlighter_216810"  cpp"=""><div><a href="http://bigasp.com/archives/458#" command_help=""  help"="">?</a></div><table cellpadding="0" cellspacing="0" border="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div></td><td><div><div number1="" index0=""  alt2"=""><code keyword=""  bold"="">explicit</code> <code plain"="">CrashReportSender(</code><code keyword=""  bold"="">const</code> <code plain"="">wstring &amp;checkpoint_file);</code></div></div></td></tr></tbody></table></div></div> <p>这个文件只有一个作用，就是用来保存上次上传崩溃的时间和今天上传过的崩溃的次数。通过这个文件，我们就可以来设置每日上传的崩溃的最大数量。</p> <div><div id="highlighter_535960"  cpp"=""><div><a href="http://bigasp.com/archives/458#" command_help=""  help"="">?</a></div><table cellpadding="0" cellspacing="0" border="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div><div number22="" index21=""  alt1"="">22</div><div number23="" index22=""  alt2"="">23</div><div number24="" index23=""  alt1"="">24</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">CrashReportSender::CrashReportSender(</code><code keyword=""  bold"="">const</code> <code plain"="">wstring &amp;checkpoint_file)</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">: checkpoint_file_(checkpoint_file),</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">max_reports_per_day_(-1),</code></div><div number4="" index3=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">last_sent_date_(-1),</code></div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">reports_sent_(0) {</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code color1=""  bold"="">FILE</code> <code plain"="">*fd;</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code> <code plain"="">(OpenCheckpointFile(L</code><code string"="">"r"</code><code plain"="">, &amp;fd) == 0) {</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">ReadCheckpoint(fd);</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code functions=""  bold"="">fclose</code><code plain"="">(fd);</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">}</code></div><div number11="" index10=""  alt2"=""><code plain"="">}</code></div><div number12="" index11=""  alt1"="">&nbsp;</div><div number13="" index12=""  alt2"=""><code plain"="">ReportResult CrashReportSender::SendCrashReport(</code></div><div number14="" index13=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">const</code> <code plain"="">wstring &amp;url, </code><code keyword=""  bold"="">const</code> <code plain"="">map&lt;wstring, wstring&gt; &amp;parameters,</code></div><div number15="" index14=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">const</code> <code plain"="">wstring &amp;dump_file_name, wstring *report_code) {</code></div><div number16="" index15=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code color1=""  bold"="">int</code> <code plain"="">today = GetCurrentDate();</code></div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code> <code plain"="">(today == last_sent_date_ &amp;&amp;</code></div><div number18="" index17=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">max_reports_per_day_ != -1 &amp;&amp;</code></div><div number19="" index18=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">reports_sent_ &gt;= max_reports_per_day_) {</code></div><div number20="" index19=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code plain"="">RESULT_THROTTLED;</code></div><div number21="" index20=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">}</code></div><div number22="" index21=""  alt1"="">&nbsp;</div><div number23="" index22=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code comments"="">// 上传文件部分代码，省略</code></div><div number24="" index23=""  alt1"=""><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <p>调整每日上传崩溃的最大数量的函数是set_max_reports_per_day。</p> <p>需要注意的是：在上传dump文件的时候，crash_report_sender并不会对dump文件进行分析，而是直接上传整个dump文件， 如果你需要上传的dump文件非常大的话，可以考虑把崩溃分析处理的逻辑放入前台，通过去重或者直接上传分析结果，减少上传的文件大小。</p> <h3><strong>breakpad存在的问题</strong></h3> <h3><span style="font-weight: normal; font-size: 13px;">进程外生成dump有很多好处，其中最大的好处就是不会被崩溃进程影响，这样dump的过程就不容易出错，但是这样也有一定的弊端。</span></h3> <p><strong>1. 部分崩溃无法抓取<br /> </strong>在一些极端的崩溃，如堆栈溢出之类的崩溃，进程外抓取dump有时候会失败。</p> <p><strong>2. 无法抓取死锁或者其他原因导致的进程僵死<br /> </strong>breakpad现在没有检测进程死锁的代码，也没有在服务端控制客户端请求dump的代码，所以现在breakpad无法抓取死锁等进程僵死的问题。不过因为breakpad的定位是处理崩溃，如果有这种需要的童鞋，可以自行修改breakpad的代码，添加这些功能。</p> <p><strong>3. 对服务端有依赖<br /> </strong>如果指定了在使用进程外抓取dump，breakpad对服务端就有依赖。主要体现在抓取dump时，如果服务端不存在，客户端将无法正常抓取dump，甚至有时会出现阻塞。</p> <p>当然对于这些问题，随着breakpad的发展肯定会越来越完善。如果，你遇到了了这些问题，而又绕过不了，那就改代码，并且提交给breakpad吧，开源项目就是这么发展的。</p> <p>好，到此breakpad的Windows实现就已经说完了，如果有神马问题，还请多多指教。谢谢大家。</p><p style="margin-bottom:0pt; margin-top:0pt; "><a href="http://www.0531jsk.com/"><span style=" color:#0000ff; text-decoration:underline ;font-family:'宋体'; ">北京德胜门中医院</span></a><a href="http://www.0531jsk.com/"><span style=" color:#0000ff; text-decoration:underline ;font-family:'宋体'; ">http://www.0531jsk.com/</span></a><span style=" font-size:10.5000pt; font-family:'宋体'; ">德胜门中医院</span></p></div><img src ="http://www.cppblog.com/lauer3912/aggbug/159785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-11-07 21:36 <a href="http://www.cppblog.com/lauer3912/archive/2011/11/07/159785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Breakpad 完全解析（一） —— Windows入门篇</title><link>http://www.cppblog.com/lauer3912/archive/2011/11/07/159784.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 07 Nov 2011 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/11/07/159784.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/159784.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/11/07/159784.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/159784.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/159784.html</trackback:ping><description><![CDATA[<div><h2>Google Breakpad 完全解析（一） &#8212;&#8212; Windows入门篇</h2> 2011年01月23日 &#8212; Asp J   <div><h3>Table of contents for Google Breakpad 完全解析</h3><ol><li>Google Breakpad 完全解析（一） &#8212;&#8212; Windows入门篇</li><li><a href="http://bigasp.com/archives/458" title="Google Breakpad 完全解析（二） &#8212;&#8212; Windows前台实现篇">Google Breakpad 完全解析（二） &#8212;&#8212; Windows前台实现篇</a></li></ol></div> <p>原创文章，转载请标明出处：Soul Apogee (<a href="http://bigasp.com/" target="_blank">http://bigasp.com</a>)，谢谢。  </p> <p><a title="Google Breakpad" href="http://code.google.com/p/google-breakpad/" target="_blank">Google breakpad</a>是 一个非常实用的跨平台的崩溃转储和分析模块，他支持Windows，Linux和Mac和Solaris。由于他本身跨平台，所以很大的减少我们在平台移 植时的工作，毕竟崩溃转储，每个平台下都不同，使用起来很难统一，而Google  breakpad就帮我们做到了这一点，不管是哪个平台下的崩溃，都能够进行统一的分析。现在很多工程都在使用他：最著名的几个如 Chrome，Firefox，Picasa和Google  Earth。另外他的License是BSD的，也就是说，我们即便是在商业软件中使用，也是合法的，哈哈，这么好的东西，我们能放过么？现在就让我们来 看看这个神奇的软件吧。</p> <h3><strong>原理简介</strong></h3> <p>breakpad抓取dump的方式和一般我们抓取dump的方式不一样。在breakpad的wiki上有一幅图可以很好的概括他的原理。</p> <p><img title="breakpad" src="http://google-breakpad.googlecode.com/svn/wiki/breakpad.png" alt="" height="464" width="425" /></p> <p>breakpad把应用程序分成三个部分，代码，breakpad客户端和调试信息。</p> <p>1. 在build system中，通过symbol dumper用平台相关的调试信息生成平台无关的symbol文件。这样做的好处很明显，一旦平台无关了，所有平台的崩溃就可以做统一的分析了。<br /> 2. breakpad采取进程外转储和分析崩溃的方式，他使用C/S结构，客户端用来捕获当前进程中发生的崩溃，并通知服务端崩溃发生。服务端用来响应客户端，抓取dump文件。这样做的目的是为了减少崩溃进程对dump的影响。<br /> 3. Dump生成后转发到崩溃分析器中，这个部分可以在本地也可以在服务器上，他对Dump文件进行解析，生成可读的堆栈信息。</p> <p>这就是breakpad处理dump大概的流程。</p> <p>对于原理的介绍google写的已经相当好了。更多的详细信息，可以直接移步到<a href="http://code.google.com/p/google-breakpad/w/list" target="_blank">breakpad的wiki</a>。</p> <h3><strong>安装和编译</strong></h3> <p>breakpad的编译比较曲折，所以在此记录一下。</p> <p>编译breakpad，请确认你的机器上装有以下的软件：<br /> 1. <a href="http://www.python.org/download/releases/2.4.3/" target="_blank">python 2.4.3</a><a href="http://www.python.org/download/releases/2.4.3/" target="_blank"><br /> </a>请不要使用python3，会报错。另外python2中推荐这个版本，使用新的版本在编译其他google的工程时有时会报错</p> <p>2. <a href="http://www.google.com/search?q=windows+sdk+7" target="_blank">Windows SDK 7</a><a href="http://www.google.com/search?q=windows+sdk+7" target="_blank"><br /> </a>如果没有这个，编译会报错。另外这个是在线安装，时间很久，最好并行做其他的事情。</p> <p>3. VS2005的补丁<br /> KB918559<br /> KB926601<br /> KB935225<br /> KB943969<br /> KB947315</p> <p>已经安装了以上软件的童鞋，就可以开始进行下面的工作鸟</p> <p>1. 使用svn把代码<a href="http://code.google.com/p/google-breakpad/source/checkout" target="_blank">checkout</a>下来</p> <div><div id="highlighter_301422"  shell"=""><div><a href="http://bigasp.com/archives/450#" command_help=""  help"="">?</a></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div></td><td><div><div number1="" index0=""  alt2"=""><code comments"=""># Non-members may check out a read-only working copy anonymously over HTTP.</code></div><div number2="" index1=""  alt1"=""><code plain"="">svn checkout http:</code><code plain"="">//google-breakpad</code><code plain"="">.googlecode.com</code><code plain"="">/svn/trunk/</code> <code plain"="">google-breakpad-</code><code functions"="">read</code><code plain"="">-only</code></div></div></td></tr></tbody></table></div></div> <p>2. 设置Windows SDK 7<br /> 装过其他版本Windows SDK的童鞋，记得一定要进行这一步，SDK的安装程序，并不会帮你设置VS。<br /> 运行开始菜单-&gt;程序-&gt;Microsoft Windows SDK v7.0-&gt;Visual Studio  Registration-&gt;Windows SDK Configuration Tool，选择v7.0，点击Make Current。</p> <p>3. 为python设置环境变量<br /> 由于breakpad使用python来生成Windows下的工程文件，所以需要将python所在目录，设置到环境变量PATH中去。</p> <p>4. 生成Windows工程文件</p> <div><div id="highlighter_825083"  shell"=""><div><a href="http://bigasp.com/archives/450#" command_help=""  help"="">?</a></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div></td><td><div><div number1="" index0=""  alt2"=""><code functions"="">cd</code> <code string"="">"源码目录/src/tools/gyp"</code></div><div number2="" index1=""  alt1"="">&nbsp;</div><div number3="" index2=""  alt2"=""><code comments"=""># 注意，此处不能使用全路径，不然会出错</code></div><div number4="" index3=""  alt1"=""><code plain"="">gyp.bat </code><code string"="">"../../client/windows/breakpad_client.gyp"</code></div></div></td></tr></tbody></table></div></div> <p>此时，在src/client/windows下就可以看到生成好的breakpad_client.sln了。运行吧！</p> <p>5. Hello World!<br /> 编译build all，现在一般是不会报错了，如果报错，请检查是不是漏了什么步骤，特别是补丁。<br /> 编译完成之后，运行crash_generation_app吧，这是他的测试程序，dump的默认位置保存在C:Dumps下，请注意先建立好目录，不然会无法使用。<br /> 启动测试程序之后，此时还不能抓取dump，因为这个是breakpad中的服务器端，需要再启动一个测试程序，在第二个测试程序中，我们就可以试验Client菜单中的各种崩溃了。这些崩溃都会被抓住转存到C:Dumps目录下。</p> <h3><strong>如何使用breakpad</strong></h3> <p> </p> <p>在Windows下<a href="http://code.google.com/p/google-breakpad/wiki/WindowsClientIntegration" target="_blank">使用breakpad的方法</a>很简单，只需要创建一个ExceptionHandler的类即可，大家可以在crash_generation_app这个工程中找到示例代码，也可以直接<a href="http://code.google.com/p/google-breakpad/wiki/WindowsClientIntegration" target="_blank">移步</a>Wiki，上面说的也很详细。</p> <p>1.进程内抓取Dump文件</p> <p>进程内抓取Dump文件是最简单的breakpad的用法。使用方法很简单：</p> <div><div id="highlighter_394770"  cpp"=""><div><a href="http://bigasp.com/archives/450#" command_help=""  help"="">?</a></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div></td><td><div><div number1="" index0=""  alt2"=""><code keyword=""  bold"="">const</code> <code plain"="">std::wstring s_strCrashDir = L</code><code string"="">"c:\dumps"</code><code plain"="">;</code></div><div number2="" index1=""  alt1"="">&nbsp;</div><div number3="" index2=""  alt2"=""><code color1=""  bold"="">bool</code></div><div number4="" index3=""  alt1"=""><code plain"="">InitBreakpad()</code></div><div number5="" index4=""  alt2"=""><code plain"="">{</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">google_breakpad::ExceptionHandler *pCrashHandler =</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">new</code> <code plain"="">google_breakpad::ExceptionHandler(s_strCrashDir,</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onExceptionFilter,</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onMinidumpDumped,</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">google_breakpad::ExceptionHandler::HANDLER_ALL,</code></div><div number12="" index11=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">MiniDumpNormal,</code></div><div number13="" index12=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number14="" index13=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL);</code></div><div number15="" index14=""  alt2"="">&nbsp;</div><div number16="" index15=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code><code plain"="">(pCrashHandler == NULL) {</code></div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code keyword=""  bold"="">false</code><code plain"="">;</code></div><div number18="" index17=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number19="" index18=""  alt2"="">&nbsp;</div><div number20="" index19=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code keyword=""  bold"="">true</code><code plain"="">;</code></div><div number21="" index20=""  alt2"=""><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <p>2.进程外抓取Dump文件</p> <p>使用进程外抓取Dump时，需要指定服务端和客户端，在服务端中需要创建CrashGenerationServer的实例，而在客户端中则只需要创建ExceptionHandler即可。此外，如果服务端自己需要抓进程内的Dump，请将pipe的参数置为NULL。</p> <div><div id="highlighter_709395"  cpp"=""><div><a href="http://bigasp.com/archives/450#" command_help=""  help"="">?</a></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div><div number22="" index21=""  alt1"="">22</div><div number23="" index22=""  alt2"="">23</div><div number24="" index23=""  alt1"="">24</div><div number25="" index24=""  alt2"="">25</div><div number26="" index25=""  alt1"="">26</div><div number27="" index26=""  alt2"="">27</div><div number28="" index27=""  alt1"="">28</div><div number29="" index28=""  alt2"="">29</div><div number30="" index29=""  alt1"="">30</div><div number31="" index30=""  alt2"="">31</div><div number32="" index31=""  alt1"="">32</div><div number33="" index32=""  alt2"="">33</div><div number34="" index33=""  alt1"="">34</div><div number35="" index34=""  alt2"="">35</div><div number36="" index35=""  alt1"="">36</div><div number37="" index36=""  alt2"="">37</div><div number38="" index37=""  alt1"="">38</div><div number39="" index38=""  alt2"="">39</div><div number40="" index39=""  alt1"="">40</div><div number41="" index40=""  alt2"="">41</div><div number42="" index41=""  alt1"="">42</div><div number43="" index42=""  alt2"="">43</div><div number44="" index43=""  alt1"="">44</div></td><td><div><div number1="" index0=""  alt2"=""><code keyword=""  bold"="">const</code> <code color1=""  bold"="">wchar_t</code> <code plain"="">s_pPipeName[] = L</code><code string"="">"\\.\pipe\breakpad\crash_handler_server"</code><code plain"="">;</code></div><div number2="" index1=""  alt1"=""><code keyword=""  bold"="">const</code> <code plain"="">std::wstring s_strCrashDir = L</code><code string"="">"c:\dumps"</code><code plain"="">;</code></div><div number3="" index2=""  alt2"="">&nbsp;</div><div number4="" index3=""  alt1"=""><code color1=""  bold"="">bool</code></div><div number5="" index4=""  alt2"=""><code plain"="">InitBreakpad()</code></div><div number6="" index5=""  alt1"=""><code plain"="">{</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">google_breakpad::CrashGenerationServer *pCrashServer =</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">new</code> <code plain"="">google_breakpad::CrashGenerationServer(s_pPipeName,</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onClientConnected,</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number12="" index11=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onClientDumpRequest,</code></div><div number13="" index12=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number14="" index13=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onClientExited,</code></div><div number15="" index14=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number16="" index15=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">true</code><code plain"="">,</code></div><div number17="" index16=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">&amp;s_strCrashDir);</code></div><div number18="" index17=""  alt1"="">&nbsp;</div><div number19="" index18=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code><code plain"="">(pCrashServer == NULL) {</code></div><div number20="" index19=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code keyword=""  bold"="">false</code><code plain"="">;</code></div><div number21="" index20=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number22="" index21=""  alt1"="">&nbsp;</div><div number23="" index22=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code comments"="">// 如果已经服务端已经启动了，此处启动会失败</code></div><div number24="" index23=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code><code plain"="">(!pCrashServer-&gt;Start()) {</code></div><div number25="" index24=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">delete</code> <code plain"="">pCrashServer;</code></div><div number26="" index25=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">pCrashServer = NULL;</code></div><div number27="" index26=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number28="" index27=""  alt1"="">&nbsp;</div><div number29="" index28=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">google_breakpad::ExceptionHandler *pCrashHandler =</code></div><div number30="" index29=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">new</code> <code plain"="">google_breakpad::ExceptionHandler(s_strCrashDir,</code></div><div number31="" index30=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onExceptionFilter,</code></div><div number32="" index31=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">onMinidumpDumped,</code></div><div number33="" index32=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL,</code></div><div number34="" index33=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">google_breakpad::ExceptionHandler::HANDLER_ALL,</code></div><div number35="" index34=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">MiniDumpNormal,</code></div><div number36="" index35=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">(pCrashServer == NULL) ? s_pPipeName : NULL, </code><code comments"="">// 如果是服务端，则直接使用进程内dump</code></div><div number37="" index36=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">NULL);</code></div><div number38="" index37=""  alt1"="">&nbsp;</div><div number39="" index38=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">if</code><code plain"="">(pCrashHandler == NULL) {</code></div><div number40="" index39=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code keyword=""  bold"="">false</code><code plain"="">;</code></div><div number41="" index40=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number42="" index41=""  alt1"="">&nbsp;</div><div number43="" index42=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword=""  bold"="">return</code> <code keyword=""  bold"="">true</code><code plain"="">;</code></div><div number44="" index43=""  alt1"=""><code plain"="">}</code></div></div></td></tr></tbody></table></div></div> <p>使用breakpad的时候，有两个地方需要注意：<br /> 1. 记得把breakpad的solution下的几个工程，包含到你开发的工程中，或者直接包含他们的lib。<br /> common：基础功能，包含一个对GUID的封装和http上传的类。<br /> exception_handler：用来捕获崩溃的类。<br /> crash_generation_server：breakpad的服务端，用来在产生崩溃时抓取dump。<br /> crash_generation_client：breakpad的客户端，用来捕获当前进程的崩溃。</p> <p>2. 在初始化breakpad之前，记得先创建好dump文件的目录，不然breakpad服务端将不能正常的写dump，这会导致breakpad客户端在崩溃时无限等待服务端dump写完的消息，最后失去响应。</p></div><img src ="http://www.cppblog.com/lauer3912/aggbug/159784.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-11-07 21:34 <a href="http://www.cppblog.com/lauer3912/archive/2011/11/07/159784.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调试Release发布版程序的Crash错误 （转）</title><link>http://www.cppblog.com/lauer3912/archive/2011/11/07/159781.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 07 Nov 2011 13:15:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/11/07/159781.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/159781.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/11/07/159781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/159781.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/159781.html</trackback:ping><description><![CDATA[<div><h1><a id="viewpost1_TitleUrl" href="../../Walker/articles/146153.html">调试Release发布版程序的Crash错误 （转）</a></h1> 	 		<div> 			<h2><a id="viewpost1_TitleUrl" href="../../woaidongmao/archive/2011/05/10/146092.html">调试Release发布版程序的Crash错误</a> </h2> <div> <p><a title="http://blog.sina.com.cn/s/blog_48f93b530100fsln.html" href="http://blog.sina.com.cn/s/blog_48f93b530100fsln.html">http://blog.sina.com.cn/s/blog_48f93b530100fsln.html</a></p> <p>&nbsp;</p> <p>在<span>Windows平台下用C++开发应用程序，最不想见到的情况恐怕就是程序崩溃，而要想解决引起问题的bug，最困难的应该就是调试release版本了。因为release版本来就少了很多调试信息，更何况一般都是发布出去由用户使用，crash的现场很难保留和重现。本文将给出几个解决方案，完成对release版应用程序crash错误的调试。（本文只讨论Windows平台MSVC环境下的调试，对于其他平台和开发环境没有关注，请大家自己借鉴和尝试。）</span></p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp; <wbr><strong>方案一：崩溃地址</strong> <span><strong><span>+ MAP</span></strong></span><strong>文件</strong></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>这种方案只能对<span><span>VC7</span>以前的版本开发的程序使用。<span>&nbsp;<wbr></span></span></p>  <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>1</strong></span><strong>、崩溃地址</strong></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>所谓崩溃地址就是引起程序崩溃的内存地址，在<span>WinXP</span>下应用程序<span>crash</span>的对话框如下图：</span></p> <p align="center"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fsln&amp;url=http://s5.sinaimg.cn/orignal/48f93b53g79aad1fff694&amp;690" target="_blank"><span><span><img title="clip_image001" alt="clip_image001" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image001_0ad42579-f1c9-44ae-b2f8-b50b8a737e0d.jpg" height="181" width="424" border="0" /></span></span></a></p> <p align="center"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fsln&amp;url=http://s7.sinaimg.cn/orignal/48f93b53g79aad2c60546&amp;690" target="_blank"><span><span><img title="clip_image002" alt="clip_image002" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image002_cb3f00fa-aa22-4301-a42c-92c12dff2ea4.jpg" height="120" width="494" border="0" /></span></span></a></p> <p align="center"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fsln&amp;url=http://s2.sinaimg.cn/orignal/48f93b53g79aad34a5521&amp;690" target="_blank"><span><span><img title="clip_image003" alt="clip_image003" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image003_fea81ac9-41ea-42be-a24f-d0fe99dafa80.jpg" height="380" width="494" border="0" /></span></span></a></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><span>上面第<span>2</span>张图中画红线的值为<span>crash</span>的代码偏移地址，第<span>3</span>张图为即<span>crash</span>绝对地址；一般引起<span>crash</span>的原因多为内存操作错误，我们用这两个地址和<span>MAP</span>文件就能定位出错的代码行。</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>2</strong></span><strong>、<span><span>MAP</span>文件</span></strong></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> MAP</span>文件是记录应用程序信息的文件（文本文件），里面大概包含了程序的全局符号、源码模块名、源码文件和行号等信息，而这些信息能够帮助我们定位出错的代码行。</p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>怎样生成<span><span>MAP</span>文件呢？以<span>VC6</span>为例，在 <span>Project Settings -&gt; C/C++ <wbr>-&gt; Debug info</span>中，选择 <span>Line Numbers Only </span>；在 <span>Project Settings -&gt; Link </span>中，选择 <span>Generate mapfile</span>项，并在<span>Project Options </span>里面输入 </span><span>/MAPINFO:LINES</span> 和 <span><span>/MAPINFO:EXPORTS</span>，重新编译程序就会生成<span>.map</span>文件。</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>以上设置对应的编译链接选项分别分：</p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><strong><span>/Zi</span></strong> &#8212; 表示生成<span><span>pdb</span>调试信息；</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><strong><span>/MAP[:filename]</span></strong> &#8212; 表示生成<span><span>map</span>文件名；</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><strong><span>/MAPINFO:EXPORTS <wbr></span></strong>&#8212; 表示生成的<span><span>map</span>文件中加入<span>exported functions</span>（生成<span>DLL</span>文件时）；</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><strong><span>/MAPINFO:LINES <wbr></span></strong>&#8212; 表示生成的<span><span>map</span>文件中加入代码行信息。</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>由于<span><span>/MAPINFO:LINES</span>选项在<span>VC8</span>以后的版本中不再支持，因此通过<span>MAP</span>文件中的信息和<span>crash</span>地址定位出错代码行就比较困难了，所以这种方案只能在<span>VC7</span>及以前的版本中使用。</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>一个<span>MAP</span>文件片段示例如下：<span>&nbsp;<wbr></span></span></p>  <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fsln&amp;url=http://s4.sinaimg.cn/orignal/48f93b53g79aae50a0e23&amp;690" target="_blank"><span><span><img title="clip_image004" alt="clip_image004" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image004_fbf07de5-1b63-4473-917f-f6695904c9be.jpg" height="229" width="494" border="0" /></span>&nbsp;<wbr></span></a>&nbsp;<wbr></span></p>  <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fsln&amp;url=http://s1.sinaimg.cn/orignal/48f93b53g79aae6db2060&amp;690" target="_blank"><span><span><img title="clip_image005" alt="clip_image005" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image005_93f97fcb-0900-4f57-baf2-29a04f821fa2.jpg" height="227" width="494" border="0" /></span></span></a></span></p>  <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><span>图中<span>Rva+Base</span>列的地址为该行函数对应的函数绝对地址，<span>Address</span>列中冒号后面的地址为函数相对偏移地址。<span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span></span></p>  <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>3</strong></span><strong>、定位<span><span>crash</span>代码</span></strong></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>有了上面的介绍，定位<span><span>crash</span>代码就很简单了。用下面的公式来进行定位：</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span><strong>崩溃行偏移 <span><span>= </span>崩溃地址 <span>- </span>崩溃函数绝对地址 <span>+ </span>函数相对偏移</span></strong></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> </span>我们首先根据崩溃地址（绝对地址），按照找到第<span><span>2</span>张图中<span>Rva+Base</span>列的地址找到发生崩溃的函数（即崩溃地址大于该函数行的<span>Rva+Base</span>地址且小于下个函数的地址），然后找到该行对应的函数相对偏移地址，带入公式中，就得到了崩溃行偏移，该值表示崩溃行的代码相对于代码所在函数的偏移量。用该值去与第<span>3</span>张图中对应函数冒号后面的偏移量去比较，最接近的值前面的那个十进制数即为代码所在函数中的行号。</span></p> <p><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ok</span>，到此我们已经成功找到了崩溃的代码行，只不过这种方法还是比较费力，并且限制比较多，我们看看下面的方案。</p> <p>上篇给出的方案一还要补充几句。通过<span>&#8220;crash地址 + MAP文件&#8221;来定位出错代码位置虽然需要经过比较复杂的地址计算，但却是最简单实现的方式。如果仅仅想通过崩溃地址定位出错的函数，就更加方便了。我在网上找到一个解析MAP文件的小工具，可以非常清晰的列出每个函数的地址，并且可以将分析表格导出为Excel文件。工具下载地址：<a href="http://e.ys168.com/?tinyfun"><span>http://e.ys168.com/?tinyfun</span></a></span>，工具目录下VCMapper.exe。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 另外上篇主要参考两篇文章：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://www.vckbase.com/document/viewdoc/?id=908"><span>http://www.vckbase.com/document/viewdoc/?id=908</span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://www.vckbase.com/document/viewdoc/?id=1473"><span>http://www.vckbase.com/document/viewdoc/?id=1473</span></a></p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>方案二：崩溃地址<span> + MAP文件 + COD文件</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 由于<span>VC8以后的版本都不再支持MAP文件中产生代码行信息，因此我们寻找另一种定位方式：COD文件。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>1</span></strong><strong>、<span>COD文件</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> COD文件是一个包含了汇编码、二进制机器码和源代码对应信息的文件，每一个<span>cpp都对应一个COD文件。通过这个文件，我们可以非常方便地进行定位。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在<span>VC6中生成COD文件的设置方式为：Project Settings -&gt; C/C++，在 Category 中选 Listing Files，在 Listing file type 组合框中选 Assembly，Machine code，and source。在VC8中生成COD文件的设置方式为：Project Properties -&gt; C/C++ -&gt; Output Files -&gt; Assembler Output 项，选择 Assembly，Machine code，and Source(/Facs)。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>2</span></strong><strong>、定位崩溃行</strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 下面通过举例进行说明。现在我有一个基于对话框的<span>MFC应用程序CrashTest，在CCrashTestDlg::OnInitDialog函数中写入导致crash的代码语句（第99行），源文件如下：</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fv7y&amp;url=http://s16.sinaimg.cn/orignal/48f93b53g79bbc36cd95f&amp;690" target="_blank"><span><span><img title="clip_image006" alt="clip_image006" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image006_887560ee-8b72-42ea-a623-220dcb47ac1f.jpg" height="169" width="360" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 根据崩溃地址（<span>0x004012A3）以及MAP文件（定位片段图片如下），定位crash函数为OnInitDialog；并且我们可以很容易地计算出崩溃地址相对于崩溃函数的偏移量为 0x004012A3 - 0x004011E0 = 0xC3。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fv7y&amp;url=http://s11.sinaimg.cn/orignal/48f93b53g79bbc5f052da&amp;690" target="_blank"><span><span><img title="clip_image007" alt="clip_image007" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image007_dc9962ce-f969-4c7f-aa0b-e973cac321ce.jpg" height="36" width="494" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 再来看看<span>CrashTestDlg.cod文件，我们根据文件中源码信息找到OnInitDialog函数信息片段：</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fv7y&amp;url=http://s4.sinaimg.cn/orignal/48f93b53g79bc3c02d3f3&amp;690" target="_blank"><span><span><img title="clip_image008" alt="clip_image008" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image008_00ac91bc-99ca-4d4f-86cd-b0d1d23bb10a.jpg" height="231" width="494" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 可以看到图片中第一行为<span>OnInitDialog函数汇编代码的起始行；找到&#8220;int * p = NULL;&#8221;这一句源码，其前面的98表示这行代码在源文件中的行号，下面的000c1表示相对于函数开始位置的偏移量，后面的&#8220;33 c0&#8221;为机器码，&#8220;xor eax，eax&#8221;为汇编码。那么我们根据前面算出来的偏移量0xC3，找到对应出错的语句为99行：&#8220;*p = 5;&#8221;。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 总结一下定位步骤：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 1) 根据公式 <strong><span>崩溃语句在函数中偏移地址<span> = 崩溃地址 - 崩溃函数地址</span></span></strong> 计算出偏移量X；</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 2) 根据公式 <strong><span>崩溃语句在<span>COD文件中地址 = 崩溃函数在COD文件中地址 + <wbr>X</span></span></strong> 计算出地址Y。其中崩溃函数在COD文件中地址为COD文件中函数起始括号&#8220;{&#8221;后面表明的地址，一般情况下为0x0000；</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 3) 根据<span>Y在COD文件中找到对应代码行。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ok，方案二介绍完了。这种方法最大的好处是没有<span>VC开发环境版本限制，而且COD文件里面包含的信息更加丰富，不但可以帮助我们定位crash，还能帮我们分析很多东西。当然，这也导致编译生成了很多信息文件。</span></p> <p>根据前面两篇博文，我们要定位崩溃行代码，必须要自己根据相关信息文件进行计算。如果需要处理的量比较大，恐怕会很费力气。有没有更简单快速的办法呢？</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 最直接的想法就是写一个小工具，根据规则和信息进行自动定位，不过开发起来也是要费一番功夫的。令人开心的是，我们可以找到类似的工具，而且是开源免费的！程序员的世界也许很多时候都是这么单纯而乐于分享！</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>方案三：崩溃地址<span> + PDB文件 + CrashFinder</span></strong></p> <p>&nbsp;<wbr><wbr>&nbsp;<wbr><wbr>&nbsp;<wbr><wbr> CrashFinder是一个开源工具，作者是<span>John Robbin，大家可以去他的blog上去找关于CrashFinder的信息。我们这里以CrashFinder2.5版本为例介绍，相关文章链接为：<a href="http://www.wintellect.com/CS/blogs/jrobbins/archive/2006/04/19/crashfinder-returns.aspx"><span>http://www.wintellect.com/CS/blogs/jrobbins/archive/2006/04/19/crashfinder-returns.aspx</span></a></span></p> <p>&nbsp;<wbr><wbr>&nbsp;<wbr><wbr>&nbsp;<wbr> <strong><span>1</span></strong><strong>、<span>PDB文件</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PDB（<span>Program Database）文件中包含了exe程序所有的调试相关信息，具体可以查阅MSDN。当编译选项设置为/Zi，链接选项设置为/DEBUG，/OPT:REF时，就会生成工程的.pdb文件。具体到VC2005中，就是 Project Propertise -&gt; C/C++ -&gt; General -&gt; Debug Information Format 项设置为 Program Database（/Zi），Linker -&gt; Debugging -&gt; Generate Debug Info 项设置为 Yes（/Debug），Linker -&gt; Optimization -&gt; References <wbr>项设置为 Eliminate <wbr>Unreferenced Data（/OPT:REF）。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 只要设置以上选项，<span>release版本也能生成PDB文件。当然，对应的应用程序也会稍大。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>2</span></strong><strong>、<span>CrashFinder</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> CrashFinder能够运行需要两个条件：一是系统必须要有<span>dbghelp.dll文件；二是PDB文件必须与exe文件在一个路径下。对于dbghelp.dll，一般在系统system32路径下都有，如果没有下载一个放到这个目录下就可以了。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 先看一下<span>CrashFinder的界面。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p> <p align="center"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fxvm&amp;url=http://s3.sinaimg.cn/orignal/48f93b53g7a37be0ea632&amp;690" target="_blank"><span><span><img title="clip_image009" alt="clip_image009" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image009_60e666ee-6f31-4132-929c-3ef20c5a9fde.jpg" height="327" width="494" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 用起来也非常简单。首先选择<span>File-&gt;New或点击工具栏新建按钮，选择要调试的exe文件打开，会发现exe及所依赖的dll文件信息都已经加载进来。在下半部分的编辑框中输入崩溃地址（16进制），点右边的&#8220;Find&#8221;按钮，就会在下面显示崩溃的源文件路径、名称以及崩溃所在行号了，如下图所示。</span></p> <p align="center"><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100fxvm&amp;url=http://s10.sinaimg.cn/orignal/48f93b53g7a37da3b3c69&amp;690" target="_blank"><span><span><img title="clip_image010" alt="clip_image010" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image010_4b25ce3c-1bea-4818-be58-230d6cba8a6a.jpg" height="370" width="494" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 用<span>CrashFinder进行crash定位真的非常方便。但是我在使用过程中发现了一个bug，每次启动程序后，直接新建的话加载进来的exe模块都显示叉，提示找不到debug symbols。但是用打开按钮随便打开一个文件失败后，再新建就能成功。猜测可能是直接新建，定位PDB文件时的路径不对引起的。有源码，但是懒的看了呵呵，大家感兴趣可以试一下。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 好了，方案三就介绍到这里，后面还有更加强大的方案<span> : )</span></p> <p>前面几个方案都是直接定位<span>crash的代码位置，但是在比较大型的程序中，只知道这个信息还是远远不够的，我们希望知道更多关于调用函数顺序及变量值等信息，也就是crash时调用堆栈信息。</span></p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>方案四：<span>SetUnhandledExceptionFil<wbr>ter + StackWalker</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 这个方案需要自己动手往工程里添加代码了。要实现上面的想法，需要做两件事情：<span>1、需要在crash时有机会对程序堆栈进行处理；2、对堆栈信息进行收集。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>1</span></strong><strong>、<span>SetUnhandleExceptionFilt<wbr>er函数</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> Windows平台下的<span>C++程序异常通常可分为两种：结构化异常（Structured Exception，可以理解为与操作系统相关的异常）和C++异常。对于结构化异常处理（SEH），可以找到很多资料，在此不细说。对于crash错误，一般由未被正常捕获的异常引起，Windows操作系统提供了一个API函数可以在程序crash之前有机会处理这些异常，就是SetUnhandleExceptionFilt<wbr>er函数。（C++也有一个类似函数set_terminate可以处理未被捕获的C++异常。）</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> SetUnhandleExceptionFilt<wbr>er函数声明如下：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFil<wbr>ter(<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> LPTOP_LEVEL_EXCEPTION_FILTER <em>lpTopLevelExceptionFilte<wbr>r</em><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> );</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 其中<span> LPTOP_LEVEL_EXCEPTION_FILTER 定义如下：</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in struct _EXCEPTION_POINTERS *ExceptionInfo<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> );<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 简单来说，<span>SetUnhandleExceptionFilt<wbr>er允许我们设置一个自己的函数作为全局SEH过滤函数，当程序crash前会调用我们的函数进行处理。我们可以利用的是 _EXCEPTION_POINTERS 结构类型的变量ExceptionInfo，它包含了对异常的描述以及发生异常的线程状态，过滤函数可以通过返回不同的值来让系统继续运行或退出应用程序。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 关于<span> SetUnhandleExceptionFilt<wbr>er 函数的具体用法和示例请参考MSDN。</span></p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>2</span></strong><strong>、<span>StackWalker</span></strong><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 现在我们已经有机会可以在<span>crash之前对程序状态信息进行处理了，只需要生成并保存堆栈信息就大功告成了。Windows的dbghelp.dll库提供了一个函数可以得到当前堆栈信息：StackWalk64（在Win2K以前版本中为StackWalk）。该函数声明如下：</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> BOOL WINAPI StackWalk64(<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> DWORD <em>MachineType</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> HANDLE <em>hProcess</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> HANDLE <em>hThread</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in_out <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> LPSTACKFRAME64 <em>StackFrame</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in_out <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PVOID <em>ContextRecord</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PREAD_PROCESS_MEMORY_ROUTINE64 <em>ReadMemoryRoutine</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PFUNCTION_TABLE_ACCESS_ROUTINE64 <em>FunctionTableAccessRouti<wbr>ne</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PGET_MODULE_BASE_ROUTINE64 <em>GetModuleBaseRoutine</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PTRANSLATE_ADDRESS_ROUTINE64 <em>TranslateAddress</em><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> );<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 该函数的具体用法可以参考<span>MSDN。在这里推荐一个牛人写好的StackWalker，可以直接拿来用，开源的。StackWalker提供了一个基类，给出了几个简单的接口，可以方便地生成堆栈信息，并且支持一系列VC版本，非常好用。我们可以自己写一个子类，并重载虚函数OnOutput，就可以将堆栈信息输出为特定格式了。StackWalker的地址为：<a href="http://www.codeproject.com/KB/threads/StackWalker.aspx"><span>http://www.codeproject.com/KB/threads/StackWalker.aspx</span></a></span>。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 不过对于<span>Release版本来说，StackWalk64函数获得的堆栈信息有可能不完整。如果异常是由MFC的模块抛出，那么获得的堆栈可能缺少前面调用模块信息。另外，StackWalk64需要最新的dbghelp.dll文件支持才能工作；要正确输出crash的函数名和行号，需要要pdb文件支持。以上不足有可能影响输出信息的完整性和效果，而对于发布在外的程序，要带上pdb文件几乎不可能，因此这个方案还是有缺憾的，比较适用于本地的release版本调试。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 下一篇我们将介绍一个更加完善的解决方案</p> <p>当我们把自己的<span>release版本程序发布出去以后，一般都是在用户的机器上运行。这种情况下，对于第四种方案，因为需要pdb文件才能够正确生成堆栈调用的函数行号及代码行号，因此方案四只适用于本地release版的调试，否则只能生成不完整的堆栈信息。对于前三种方案，其实只需要用户告知崩溃地址，然后在本地查找crash地址就可以了，但是定位crash的过程非常不方便，如果crash的情况比较多，前三种方案都不合适。而且，前三种方案均不能生成堆栈调用信息，对于debug的作用有限。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 下面我们就来看一个更加完善的解决方案。</p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>方案五：<span>SetUnhandledExceptionFil<wbr><wbr>ter + Minidump</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> SetUnhandleExceptionFilt<wbr>er函数我们已经介绍过了，本方案的思路还是要利用我们自己的异常处理函数，来生成<span>minidump文件。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>1</span></strong><strong>、<span>Minidump概念</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> minidump（小存储器转储）可以理解为一个<span>dump文件，里面记录了能够帮助调试crash的最小有用信息。实际上，如果你在 系统属性 -&gt; 高级 -&gt; 启动和故障恢复 -&gt; 设置 -&gt; 写入调试信息 中选择&#8220;小内存转储(64 KB)&#8221;的话，当系统意外停止时都会在C:\Windows\Minidump\路径下生成一个.dmp后缀的文件，这个文件就是minidump文件，只不过这个是内核态的minidump。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>我们要生成的是用户态的<span>minidump，文件中包含了程序运行的模块信息、线程信息、堆栈调用信息等。而且为了符合其mini的特性，dump文件是压缩过的。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>2</span></strong><strong>、生成<span>minidump文件</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 生成<span>minidump文件的API函数是MiniDumpWriteDump，该函数需要dbghelp.lib支持，其原型如下:</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> BOOL WINAPI MiniDumpWriteDump(<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> HANDLE <em>hProcess</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> DWORD <em>ProcessId</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> HANDLE <em>hFile</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> MINIDUMP_TYPE <em>DumpType</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PMINIDUMP_EXCEPTION_INFORMATION <em>ExceptionParam</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PMINIDUMP_USER_STREAM_INFORMATION <em>UserStreamParam</em>,<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> __in <wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> PMINIDUMP_CALLBACK_INFORMATION <em>CallbackParam</em><br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> );</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 在我们的异常处理函数中加入以下代码：</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> HANDLE hFile = ::CreateFile( _T("E:\\dumpfile.dmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> if( hFile != INVALID_HANDLE_VALUE)<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> {<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> MINIDUMP_EXCEPTION_INFORMATION einfo;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> einfo.ThreadId = ::GetCurrentThreadId();<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> einfo.ExceptionPointers = pExInfo;<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> einfo.ClientPointers = FALSE;</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ::MiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), hFile, MiniDumpNormal, &amp;einfo, NULL, NULL);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ::CloseHandle(hFile);<br />&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> }</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 其中，<span>pExInfo变量为异常处理函数PEXCEPTION_POINTERS类型的参数。具体请参考MSDN。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>3</span></strong><strong>、调试<span>minidump</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>调试<span>dump文件首先需要pdb文件，因此我们build程序时需要设置 Debug Infomation Format 为 &#8220;Program Database（/Zi）&#8221;。其次，我们还要确保所用的dump文件与源代码、exe、pdb文件版本是一致的，这要求我们必须维护好程序版本信息。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 调试<span>minidump最方便的环境就是VS了，我们只要将.dmp、.exe、.pdb文件放在一个路径下，保证源代码文件的路径与编译时的路径一致就可以了，剩下的就是VS帮我们完成。双击.dmp文件或者在文件打开工程中选择&#8220;dump files&#8221;，加载dump文件，然后按F5运行就能直接恢复crash时的现场了，你可以定位crash的代码，可以查看调用堆栈，可以查看线程和模块信息...一切都跟你设置断点调试一样，太强大了！看个截图吧。</span></p> <p><a href="http://photo.blog.sina.com.cn/showpic.html#blogid=48f93b530100g282&amp;url=http://s16.sinaimg.cn/orignal/48f93b53g7b0e4eff189f&amp;690" target="_blank"><span><span><img title="clip_image012" alt="clip_image012" src="../../images/cppblog_com/woaidongmao/WindowsLiveWriter/ReleaseCrash_A881/clip_image012_3df8e4ef-d0e8-49d3-a9af-47f58cc713c6.jpg" height="469" width="616" border="0" /></span></span></a></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 需要注意的是，对于<span>release版的程序来说，很多代码是经过编译器优化过的，因此定位的时候可能会有所偏差，大家可以考虑设置选项去掉代码优化。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 其他可以调试<span>minidump的工具还有WinDbg等，大家可以查阅相关资料。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 本文主要参考了这篇文章：<span><a href="http://vicchina.51.net/research/other/seh/minidumps/intro.htm"><span>http://vicchina.51.net/research/other/seh/minidumps/intro.htm</span></a></span>。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 下一篇，我们将给出一个调试<span>release发布程序的完美解决方案，适合用户量较大的应用发布程序的调试。</span></p> <p>上一篇我们已经给出了方案，能够非常方便的通过<span>dump文件对crash错误进行调试和定位；从整个流程上看还差最后一步，即怎样拿到crash时产生的dump文件。如果可以让用户把文件发送过来自然不错，但对于类似免费共享软件等在互联网上发布的程序呢？我们的用户是不确定的，而且用户量有可能非常大，即使我们能想办法联系到用户，总不能挨个去收集crash信息吧。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 我们需要一种方案，能够提供<span>crash信息汇报功能。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 我们可以架设一台服务器专门进行信息收集，只要客户端在<span>crash时正确汇报即可，但是相应的维护成本和开发难度也不可忽视。有没有更简单的方法呢？还记得我的博文&#8220;<a href="http://blog.sina.com.cn/s/blog_48f93b530100esmg.html" target="_blank"><span><span>为程序添加自动发送Email</span><span>功能</span></span></a>&#8221;</span>吗？这就是简单有效的方法！</p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong>方案六：<span>minidump + email</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 我们只需要在异常处理时，先生成<span>minidump信息文件，再用email方式将文件发送到指定邮箱就行了。剩下的就是我们每天查看邮箱，提取dump文件进行调试了。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>1</span></strong><strong>、<span>Email功能</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 首先我们来看一下<span>email发送都需要哪些相关信息。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> a、发送端邮箱帐户；</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> b、接收端邮箱帐户；</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> c、<span>email标题，一般应有软件名称及版本信息；</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> d、<span>email正文，一般应有简单的crash信息提示，以区别不同原因造成的crash；</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>e、<span>email附件，当然就是我们的dump文件了，还可以加上软件生成的log文件等。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 当然，对于标题应该尽量多加一些信息区别引起<span>crash的原因，比如将crash的地址信息加到标题中；因为当每天有成百上千的crash汇报上来，重复的crash占大多数，把时间都花在区分它们身上有点太浪费。由此看来，前面方案中提到的StackWalker还是有些用处的，我们可以用它来生成一些crash的文字描述信息，写到标题或正文中去。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> dump文件的大小是否适合作为邮件的附件呢？实际上<span>minidump产生的文件一般在几K到几十K之间，作为email的附件没有任何问题。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 关于发送<span>email相关技术细节，已经在&#8220;<a href="http://blog.sina.com.cn/s/blog_48f93b530100esmg.html" target="_blank"><span><span>为程序添加自动发送Email</span><span>功能</span></span></a>&#8221;</span>文中介绍了，大家可以参考。其实，对接受邮箱中邮件的处理还是很费时费力的，大家可以考虑写一些脚本将处理流程自动化，提高效率。</p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> <strong><span>2</span></strong><strong>、<span>google breakpad</span></strong></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> google breakpad是一个开源的跨平台<span>crash report系统，光从开源和跨平台这两个特点上来看，它就足以称的上是一个完善而有效的工具了。其实，breakpad在整个crash report层次上给出了一个系统级的解决方案，也就是说它几乎能适应各种软件、各种平台的应用要求。</span></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> breakpad的整体思路跟上面介绍的方案是相似的，只不过最后提交<span>dump文件的方式更加完善。大家有兴趣可以去它的官方网址查阅相关资料：<a href="http://code.google.com/p/google-breakpad/"><span>http://code.google.com/p/google-breakpad/</span></a></span>。</p> <p>&nbsp;<wbr></p> <p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> ok，关于调试<span>release发布程序的crash错误系列文章就写完了。这几篇文章给出的方案由简单到复杂，由简陋到完善，对crash调试有了一个比较全面的总结。当然，其中涉及到的概念和技术还很多，需要我们去不断学习和领悟，也希望大家能够互相交流。</span></p> </div>  		</div></div><img src ="http://www.cppblog.com/lauer3912/aggbug/159781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-11-07 21:15 <a href="http://www.cppblog.com/lauer3912/archive/2011/11/07/159781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DevGuide   如何有助于谷歌 c + + 测试框架  阶段实施特色</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156885.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:55:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156885.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156885.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156885.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156885.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: Simsun; line-height: normal; font-size: medium; "><div style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; font: normal normal normal 82%/normal arial, sans-serif; margin-top: 3px; margin-right: 0px; margin-bottom: 3px; margin-left: 0px; min-width: 768px; background-position: initial initial; background-repeat: initial initial; "><div class="headbg" style="margin-top: 0px; margin-right: 8px; margin-bottom: 0px; margin-left: 8px; "><div id="gaia" style="text-align: right; margin-bottom: 10px; "><span><font><font lang="zh-CHS"><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23" id="projects-dropdown" target="_top" style="color: #0000cc; text-decoration: none; "><u>我的收藏夹</u>&nbsp;<small>&#9660;</small>&nbsp;</a>|</font><font lang="zh-CHS"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide" target="_top" style="color: #0000cc; text-decoration: none; "><u>登录</u></a></font></font></span></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; left: 0pt; "></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; right: 0pt; "></div><div style="height: 1px; "></div><table cellpadding="0" cellspacing="0" itemscope="" itemtype="http://schema.org/CreativeWork" style="border-collapse: separate; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; width: 752px; "><tbody><tr style="height: 58px; "><td id="plogo" style="width: 55px; text-align: center; vertical-align: bottom; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #0000cc; "><img src="http://www.gstatic.com/codesite/ph/images/search-48.gif" alt="Logo" itemprop="image" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></a></td><td style="padding-left: 0.5em; "><div id="pname" style="font-size: 39px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #666666; text-decoration: none; "><span itemprop="name" lang="zh-CHS">googletest</span></a></div><div id="psum"><a id="project_summary_link" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #444444; text-decoration: none; "><span itemprop="description" lang="zh-CHS">谷歌 c + + 测试框架</span></a></div></td><td style="white-space: nowrap; text-align: right; vertical-align: bottom; "><form action="http://www.microsofttranslator.com/bv.aspx" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><input size="30" name="q" value="" type="text" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " />&nbsp;<input type="submit" name="projectsearch" value="Search projects" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></td></tr></tbody></table></div><div id="mt" class="gtb" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ebeff9; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #6b90da; padding-top: 5px; padding-right: 10px; padding-left: 5px; white-space: nowrap; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">项目主页</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fdownloads%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">下载</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist" class="tab active" target="_top" lang="zh-CHS" style="color: #000000; cursor: default; float: left; margin-top: 0px; margin-right: 5px; margin-bottom: -1px; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; border-top-width: 1px; border-right-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-left-style: solid; border-top-color: #6b90da; border-right-color: #6b90da; border-left-color: #6b90da; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; font-weight: bold; padding-top: 5px; padding-right: 9px; padding-bottom: 6px; padding-left: 9px; text-decoration: none; background-position: initial initial; background-repeat: initial initial; ">维基</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fissues%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">问题</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">源</a><div class="gtbc" style="clear: left; "></div></div><table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st" style="border-collapse: separate; "><tbody><tr><td class="subt" style="background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ffffff), to(#f1f1f1)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-bottom-style: solid; border-bottom-color: #cccccc; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 14px; height: 33px; "><div class="issueDetail"><div class="isf"><span class="inIssueList"><span lang="zh-CHS">搜索</span>&nbsp;<form action="http://www.microsofttranslator.com/bv.aspx" method="GET" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; display: inline; "><select id="can" name="can" style="font-family: arial, sans-serif; ">&nbsp; <option disabled="disabled">内搜索：</option>&nbsp;&nbsp; &nbsp;<option value="1">所有 wiki 页面</option>&nbsp; <option value="3">特色的页</option>&nbsp; <option value="2" selected="selected">当前页</option>&nbsp; &nbsp;&nbsp; &nbsp;<option value="4">不推荐使用的页</option>&nbsp;&nbsp; &nbsp;</select>&nbsp;<span lang="zh-CHS">对于</span>&nbsp;<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " /></span>&nbsp;<input type="submit" value="Search" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></span></div></div></td><td align="right" valign="top" class="bevel-right" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></td></tr></tbody></table><div id="maincol" style="padding-right: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; "><div id="wikipage" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #f8f8f8; padding-bottom: 10px; background-position: initial initial; background-repeat: initial initial; "><table style="border-collapse: separate; "><tbody><tr><td style="vertical-align: top; padding-left: 5px; "><div id="wikiheader" style="padding-top: 10px; margin-bottom: 12px; "><span lang="zh-CHS" style="font-size: 16px; font-weight: bold; ">DevGuide</span>&nbsp;&nbsp;<div><em lang="zh-CHS">如何有助于谷歌 c + + 测试框架</em>&nbsp;<br /><font lang="zh-CHS"><a class="label" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist%3Fq%3Dlabel%3APhase-Implementation" title="Developers' guide" target="_top" style="text-decoration: none; color: #0000cc; padding-top: 2px; ">阶段实施</a><a class="label" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist%3Fq%3Dlabel%3AFeatured" title="Listed on project home page" target="_top" style="text-decoration: none; color: #0000cc; padding-top: 2px; ">特色</a></font><div id="wikiauthor" style="clear: both; text-align: right; font-size: x-small; float: right; "><font lang="zh-CHS">由<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fu%2F%40WBhXQFBWDhlDVgF4%2F" target="_top" style="color: #0000cc; white-space: nowrap; ">w...@google.com</a>更新的<span title="Thu Aug 19 13:53:46 2010">2010 年 8 月 19 日</span></font></div></div></div><div id="wikicontent"><div class="vt" id="wikimaincol" style="vertical-align: top; padding-top: 5px; padding-right: 25px; padding-bottom: 10px; padding-left: 10px; background-color: #ffffff; min-width: 64em; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; "><p style="line-height: 1.25em; max-width: 64em; "></p><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Introduction" target="_top" lang="zh-CHS" style="color: #0000cc; ">简介</a></li><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Licensing" target="_top" lang="zh-CHS" style="color: #0000cc; ">发牌</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23The_Google_Test_Community" target="_top" lang="zh-CHS" style="color: #0000cc; ">谷歌测试社区</a></li><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Please_Be_Friendly" target="_top" lang="zh-CHS" style="color: #0000cc; ">请将友好</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Where_to_Discuss_Google_Test" target="_top" lang="zh-CHS" style="color: #0000cc; ">讨论谷歌测试的位置</a></li></ul></ul><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Working_with_the_Code" target="_top" lang="zh-CHS" style="color: #0000cc; ">使用代码</a></li><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Checking_Out_the_Source_from_Subversion" target="_top" lang="zh-CHS" style="color: #0000cc; ">签出颠覆的来源</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Compiling_from_Source" target="_top" lang="zh-CHS" style="color: #0000cc; ">从源代码编译</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Testing" target="_top" lang="zh-CHS" style="color: #0000cc; ">测试</a></li></ul><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Contributing_Code" target="_top" lang="zh-CHS" style="color: #0000cc; ">贡献代码</a></li><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Contributor_License_Agreements" target="_top" lang="zh-CHS" style="color: #0000cc; ">参与者的许可协议</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Coding_Style" target="_top" lang="zh-CHS" style="color: #0000cc; ">编码风格</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Updating_Generated_Code" target="_top" lang="zh-CHS" style="color: #0000cc; ">更新生成的代码</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Submitting_Patches" target="_top" lang="zh-CHS" style="color: #0000cc; ">提交的修补程序</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Google_Test_Committers" target="_top" lang="zh-CHS" style="color: #0000cc; ">谷歌测试独立自主</a></li></ul><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Release_Process" target="_top" lang="zh-CHS" style="color: #0000cc; ">发布过程</a></li></ul><p style="line-height: 1.25em; max-width: 64em; "></p><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">如果您有兴趣了解谷歌测试，从来源，或派遣的想法或修改项目、 建筑内部本文档将是你。</p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Introduction" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">简介</font></h1><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">首先，让我们给您项目的一些背景。</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Licensing" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">发牌</font><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Licensing" class="section_anchor" target="_top" style="color: #bbbbbb; display: inline; text-decoration: none; margin-left: 0.7em; font-size: 15px; "></a></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">根据<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fwww.opensource.org%2Flicenses%2Fbsd-license.php" rel="nofollow" target="_top" style="color: #0000cc; ">新的 BSD 许可证</a>提供所有谷歌测试源和预编译的程序包</font>.</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="The_Google_Test_Community" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">谷歌测试社区</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">谷歌测试社区已经存在，主要是透过<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fgroups.google.com%2Fgroup%2Fgoogletestframework" rel="nofollow" target="_top" style="color: #0000cc; ">讨论组</a>，<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fissues%2Flist" rel="nofollow" target="_top" style="color: #0000cc; ">问题跟踪器</a>和幅度较小，<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout" rel="nofollow" target="_top" style="color: #0000cc; ">源代码管理储存库</a>。</font><font lang="zh-CHS">你肯定鼓励参与讨论，您还可以帮助我们保持高集团的效果后，促进在此处列出的准则。</font></p><h3 style="font-size: medium; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-top-style: solid; border-top-color: #3366cc; padding-top: 0.5ex; padding-right: 0.5em; padding-bottom: 0.5ex; padding-left: 0px; margin-right: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; max-width: 700px; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; background-position: initial initial; background-repeat: initial initial; "><a name="Please_Be_Friendly" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">请将友好</font></h3><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">显示的礼貌和尊重他人是在谷歌文化的重要组成部分和我们强烈鼓励大家参与谷歌测试开发加盟不接受。</font><font lang="zh-CHS">当然，礼貌并不相同，未有建设性地不同意对方，但它意味着枚举 42 技术原因某项建议可能不是最佳选择时我们应该互相尊重。</font><font lang="zh-CHS">没有理由拮抗或轻视向任何人真诚地试图进行的讨论作出贡献。</font></p><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">肯定的是，c + + 测试是严肃的商业和其它的东西，但它也有很多乐趣。</font><font lang="zh-CHS">让我们保持这种方式。</font><font lang="zh-CHS">让我们努力成为所有开放源码中最友好的社区之一。</font></p><h3 style="font-size: medium; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-top-style: solid; border-top-color: #3366cc; padding-top: 0.5ex; padding-right: 0.5em; padding-bottom: 0.5ex; padding-left: 0px; margin-right: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; max-width: 700px; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; background-position: initial initial; background-repeat: initial initial; "><a name="Where_to_Discuss_Google_Test" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">讨论谷歌测试的位置</font></h3><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">一如既往，讨论谷歌测试的官方<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fgroups.google.com%2Fgroup%2Fgoogletestframework" rel="nofollow" target="_top" style="color: #0000cc; ">谷歌 c + + 测试框架的讨论组</a>。</font><font lang="zh-CHS">你不必实际提交代码，以便签约。</font><font lang="zh-CHS">您的参与本身是宝贵的贡献。</font></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Working_with_the_Code" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">使用代码</font></h1><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">如果你想把你的手弄脏与内谷歌测试的代码，这是你的部分。</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Checking_Out_the_Source_from_Subversion" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">签出颠覆的来源</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">签出谷歌测试源是最有用的如果您计划调整自己。</font><font lang="zh-CHS">谷歌测试使用<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fsubversion.tigris.org%2F" rel="nofollow" target="_top" style="color: #0000cc; ">颠覆</a>客户端，但 Google Code 上承载的任何其他项目签出源。</font><font lang="zh-CHS">请如何做这件事的<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout" rel="nofollow" target="_top" style="color: #0000cc; ">源代码访问页</a>，参阅该指令。</font></p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Compiling_from_Source" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">从源代码编译</font></h2><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">一旦您签出该代码，您可以找到有关如何编译它的<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2FREADME" rel="nofollow" target="_top" style="color: #0000cc; ">自述</a>文件中的说明。</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Testing" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">测试</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">一个测试框架是不好，如果本身不彻底的测试。</font><font lang="zh-CHS">测试应编写的任何新的代码，并应在提交审查不打破现有的测试验证更改。</font><font lang="zh-CHS">要执行测试，按照<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2FREADME" rel="nofollow" target="_top" style="color: #0000cc; ">自述文件</a>中的说明，并验证不存在任何故障。</font></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Contributing_Code" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">贡献代码</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">我们很激动谷歌测试现在是开源的和希望从社会得到很大的修补程序。</font><font lang="zh-CHS">在您最喜爱的 IDE 点燃并开始地敲击着这项新功能之前，不过，请花时间阅读本节和理解这一进程。</font><font lang="zh-CHS">尽管它看起来严格，我们要保持高标准的质量基本代码。</font></p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Contributor_License_Agreements" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">参与者的许可协议</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">我们可以接受任何代码之前，您必须注册参与者许可协议 (CLA)。</font><font lang="zh-CHS">共轭亚油酸保护您和我们。</font></p><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">如果您是个人写作原始源代码，你知道你自己的知识产权，那么你需要签署<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Flegal%2Findividual-cla-v1.0.html" rel="nofollow" target="_top" style="color: #0000cc; ">个别共轭亚油酸</a></font>.</li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">如果你工作的公司想要允许您将您的工作有助于谷歌测试，然后将需要签署<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Flegal%2Fcorporate-cla-v1.0.html" rel="nofollow" target="_top" style="color: #0000cc; ">公司共轭亚油酸</a></font>.</li></ul><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">按照上面的两个链接访问相应的共轭亚油酸和签署并返回它的说明。</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Coding_Style" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">编码风格</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font><font lang="zh-CHS">若要保持源一致的、 可读的 diffable 和易于合并，我们使用相当死板的编码风格，如由<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogle-styleguide%2F" rel="nofollow" target="_top" style="color: #0000cc; ">google styleguide</a>项目定义。</font><font lang="zh-CHS">预计所有修补程序将符合所述的风格<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fgoogle-styleguide.googlecode.com%2Fsvn%2Ftrunk%2Fcppguide.xml" rel="nofollow" target="_top" style="color: #0000cc; ">在这里</a></font></font>.</p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Updating_Generated_Code" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">更新生成的代码</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">谷歌测试的源代码文件的一些由泵工具 （Python 脚本） 生成。</font><font lang="zh-CHS">如果您需要更新这些文件，请修改源 （<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">foo.h.pump</tt>），并重新生成的 c + + 文件使用泵。</font><font lang="zh-CHS">您可以阅读<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FPumpManual" target="_top" style="color: #0000cc; ">PumpManual</a>的详细信息。</font></p><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Submitting_Patches" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">提交的修补程序</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">请不要提交代码。</font><font lang="zh-CHS">下面是您需要做什么：</font></p><ol style="padding-left: 25px; max-width: 62em; "><li lang="zh-CHS" style="margin-bottom: 0.3em; ">通常您应进行更改 SVN 树干的分支或标记，而不是针对后面的两个版本控制，应被视为主要为只读。</li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">决定您想提交哪些的代码。</font><font lang="zh-CHS">提交应解决一个问题中的<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fissues%2Flist" rel="nofollow" target="_top" style="color: #0000cc; ">Google 测试问题跟踪器</a>的一组更改。</font><font lang="zh-CHS">请不要混合多个逻辑更改每提交，因为它使历史难追。</font><font lang="zh-CHS">如果你想有所改变，在问题跟踪器没有一个相应的问题，请创建一个。</font></li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">此外，协调与团队成员的问题上列出。</font><font lang="zh-CHS">这可以确保工作不正在复制和沟通你的计划早一般也会导致更好的修补程序。</font></li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">确保您的代码坚守<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FDevGuide%23Coding_Style" target="_top" style="color: #0000cc; ">谷歌测试源代码样式</a></font>.</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">确保您的代码的单元测试。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">签名参与者的许可协议。</li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">创建使用<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn diff</tt>修补程序文件</font>.</li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">我们使用<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcodereview.appspot.com%2F" rel="nofollow" target="_top" style="color: #0000cc; ">里特韦尔</a>进行基于 web 的代码审查。</font><font lang="zh-CHS">您可以阅读有关该工具<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Frietveld%2Fwiki%2FCodeReviewHelp" rel="nofollow" target="_top" style="color: #0000cc; ">在这里</a>。</font><font lang="zh-CHS">当您准备就绪时上, 传您的修补程序通过冶金并通知<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">googletestframework@googlegroups.com</tt>作出检讨。</font><font lang="zh-CHS">有几种方法可以上载该修补程序。</font><font lang="zh-CHS">我们建议使用<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fscripts%2Fupload_gtest.py" rel="nofollow" target="_top" style="color: #0000cc; ">upload_gtest.py</a>脚本中，您可以查找<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">脚本 /</tt>&nbsp;SVN 树干中的文件夹。</font></li></ol><h2 style="font-size: large; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Google_Test_Committers" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">谷歌测试独立自主</font></h2><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">谷歌测试工程团队的当前成员目前是唯一的独立自主。</font><font lang="zh-CHS">在吃自己的试用的伟大传统，我们亦会规定每个新来赚取权成为委员会按照下面的过程在此文档中，谷歌测试工程团队成员编写代码始终很大，并演示重复他或她真正获取谷歌测试的禅宗。</font></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Release_Process" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">发布过程</font></h1><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">我们遵循颠覆基于项目的典型释放过程：</p><ol style="padding-left: 25px; max-width: 62em; "><li lang="zh-CHS" style="margin-bottom: 0.3em; ">创建名为<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">释放 X.Y</tt>释放分支。</li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">Bug 固定的树干 ； 添加的功能</font><font lang="zh-CHS">这些个别的修补程序合并到释放科才稳定。</font></li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">个人单点发行版 (&nbsp;<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">Z</tt>在<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">X.Y.Z</tt>) 提出从分支创建标签。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">重复步骤 2 和 3，整个一个发布周期 （如由功能或时间）。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">返回到步骤 1，创建另一个版本分支，等等。</li></ol><hr style="width: 839px; color: #cccccc; background-color: #cccccc; " /><p style="line-height: 1.25em; max-width: 64em; "><font><font lang="zh-CHS">此页基于从<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fwebtoolkit%2F" rel="nofollow" target="_top" style="color: #0000cc; ">谷歌 Web 工具包</a>项目指南<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fwebtoolkit%2Fmakinggwtbetter.html" rel="nofollow" target="_top" style="color: #0000cc; ">使 GWT 更好</a>。</font><font lang="zh-CHS">除了作为则<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fpolicies.html%23restrictions" rel="nofollow" target="_top" style="color: #0000cc; ">指出</a>，该网页的内容被许可<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcreativecommons.org%2Flicenses%2Fby%2F2.5%2F" rel="nofollow" target="_top" style="color: #0000cc; ">创新知识共享署名 2.5 许可证</a></font></font>.</p></div></div></td></tr><tr></tr></tbody></table></div><form name="delcom" action="http://code.google.com/p/googletest/w/delComment.do" method="POST" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></form></div><div id="footer" dir="ltr" style="clear: both; text-align: center; margin-top: 3.5em; margin-bottom: 1em; height: 53px; background-position: 0% 50%; background-repeat: no-repeat no-repeat; "><div class="text" style="padding-top: 20px; "><font lang="zh-CHS">&#169; 2011 Google--<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fwww.google.com%2Fprivacy.html" target="_top" style="color: #0000cc; ">私隐</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2Fterms.html" target="_top" style="color: #0000cc; ">条款</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fsupport%2F" target="_top" style="color: #0000cc; ">项目主办的帮助</a></font></div></div><div class="hostedBy" style="text-align: center; margin-top: -20px; "><span lang="zh-CHS" style="vertical-align: top; ">通过<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2F" target="_top" style="color: #0000cc; ">Google 计划主办</a>动力</span></div></div></span><img src ="http://www.cppblog.com/lauer3912/aggbug/156885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:55 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>V1_6_FAQ   提示和常见问题关于谷歌 c + + 测试框架</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156884.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:53:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156884.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156884.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156884.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我的收藏夹&nbsp;&#9660;&nbsp;|登录googletest谷歌 c + + 测试框架&nbsp;项目主页下载维基问题源搜索&nbsp;&nbsp; 内搜索：&nbsp;&nbsp; &nbsp;所有 wiki 页面&nbsp; 特色的页&nbsp; 当前页&nbsp; &nbsp;&nbsp; &nbsp;不推荐使用的页&nbsp;&nbsp; &nbsp;&nbsp;对于&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/lauer3912/archive/2011/09/26/156884.html'>阅读全文</a><img src ="http://www.cppblog.com/lauer3912/aggbug/156884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:53 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> V1_6_XcodeGuide   在 Mac OS X 上 Xcode 使用谷歌测试框架指南 </title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156882.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:48:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156882.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156882.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156882.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156882.html</trackback:ping><description><![CDATA[<font class="Apple-style-span" face="arial, sans-serif" size="3"><span class="Apple-style-span" style="line-height: normal;"><br /></span></font><span class="Apple-style-span" style="font-family: Simsun; line-height: normal; font-size: medium; "><div style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; font: normal normal normal 82%/normal arial, sans-serif; margin-top: 3px; margin-right: 0px; margin-bottom: 3px; margin-left: 0px; min-width: 768px; background-position: initial initial; background-repeat: initial initial; "><div class="headbg" style="margin-top: 0px; margin-right: 8px; margin-bottom: 0px; margin-left: 8px; "><div id="gaia" style="text-align: right; margin-bottom: 10px; "><span><font><font lang="zh-CHS"><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23" id="projects-dropdown" target="_top" style="color: #0000cc; text-decoration: none; "><u>我的收藏夹</u>&nbsp;<small>&#9660;</small>&nbsp;</a>|</font><font lang="zh-CHS"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide" target="_top" style="color: #0000cc; text-decoration: none; "><u>登录</u></a></font></font></span></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; left: 0pt; "></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; right: 0pt; "></div><div style="height: 1px; "></div><table cellpadding="0" cellspacing="0" itemscope="" itemtype="http://schema.org/CreativeWork" style="border-collapse: separate; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; width: 752px; "><tbody><tr style="height: 58px; "><td id="plogo" style="width: 55px; text-align: center; vertical-align: bottom; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #0000cc; "><img src="http://www.gstatic.com/codesite/ph/images/search-48.gif" alt="Logo" itemprop="image" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></a></td><td style="padding-left: 0.5em; "><div id="pname" style="font-size: 39px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #666666; text-decoration: none; "><span itemprop="name" lang="zh-CHS">googletest</span></a></div><div id="psum"><a id="project_summary_link" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #444444; text-decoration: none; "><span itemprop="description" lang="zh-CHS">谷歌 c + + 测试框架</span></a></div></td><td style="white-space: nowrap; text-align: right; vertical-align: bottom; "><form action="http://www.microsofttranslator.com/bv.aspx" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><input size="30" name="q" value="" type="text" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " />&nbsp;<input type="submit" name="projectsearch" value="Search projects" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></td></tr></tbody></table></div><div id="mt" class="gtb" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ebeff9; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #6b90da; padding-top: 5px; padding-right: 10px; padding-left: 5px; white-space: nowrap; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">项目主页</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fdownloads%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">下载</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist" class="tab active" target="_top" lang="zh-CHS" style="color: #000000; cursor: default; float: left; margin-top: 0px; margin-right: 5px; margin-bottom: -1px; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; border-top-width: 1px; border-right-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-left-style: solid; border-top-color: #6b90da; border-right-color: #6b90da; border-left-color: #6b90da; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; font-weight: bold; padding-top: 5px; padding-right: 9px; padding-bottom: 6px; padding-left: 9px; text-decoration: none; background-position: initial initial; background-repeat: initial initial; ">维基</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fissues%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">问题</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">源</a><div class="gtbc" style="clear: left; "></div></div><table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st" style="border-collapse: separate; "><tbody><tr><td class="subt" style="background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ffffff), to(#f1f1f1)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-bottom-style: solid; border-bottom-color: #cccccc; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 14px; height: 33px; "><div class="issueDetail"><div class="isf"><span class="inIssueList"><span lang="zh-CHS">搜索</span>&nbsp;<form action="http://www.microsofttranslator.com/bv.aspx" method="GET" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; display: inline; "><select id="can" name="can" style="font-family: arial, sans-serif; ">&nbsp; <option disabled="disabled">内搜索：</option>&nbsp;&nbsp; &nbsp;<option value="1">所有 wiki 页面</option>&nbsp; <option value="3">特色的页</option>&nbsp; <option value="2" selected="selected">当前页</option>&nbsp; &nbsp;&nbsp; &nbsp;<option value="4">不推荐使用的页</option>&nbsp;&nbsp; &nbsp;</select>&nbsp;<span lang="zh-CHS">对于</span>&nbsp;<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " /></span>&nbsp;<input type="submit" value="Search" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></span></div></div></td><td align="right" valign="top" class="bevel-right" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></td></tr></tbody></table><div id="maincol" style="padding-right: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; "><div id="wikipage" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #f8f8f8; padding-bottom: 10px; background-position: initial initial; background-repeat: initial initial; "><table style="border-collapse: separate; "><tbody><tr><td style="vertical-align: top; padding-left: 5px; "><div id="wikiheader" style="padding-top: 10px; margin-bottom: 12px; "><span lang="zh-CHS" style="font-size: 16px; font-weight: bold; ">V1_6_XcodeGuide</span>&nbsp;&nbsp;<div><em lang="zh-CHS">在 Mac OS X 上 Xcode 使用谷歌测试框架指南</em>&nbsp;<br /><a class="label" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist%3Fq%3Dlabel%3APhase-Deploy" title="How to install and configure the program" target="_top" lang="zh-CHS" style="text-decoration: none; color: #0000cc; padding-top: 2px; ">部署阶段</a><div id="wikiauthor" style="clear: both; text-align: right; font-size: x-small; float: right; "><font lang="zh-CHS">由<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fu%2F%40VBNWR1RSBxdEWgZ0%2F" target="_top" style="color: #0000cc; white-space: nowrap; ">zhanyong...@gmail.com</a>更新的<span title="Mon Apr 18 14:45:17 2011">2011 年 4 月 18 日</span></font></div></div></div><div id="wikicontent"><div class="vt" id="wikimaincol" style="vertical-align: top; padding-top: 5px; padding-right: 25px; padding-bottom: 10px; padding-left: 10px; background-color: #ffffff; min-width: 64em; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; "><p style="line-height: 1.25em; max-width: 64em; "></p><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Quick_Start" target="_top" lang="zh-CHS" style="color: #0000cc; ">快速入门</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Get_the_Source" target="_top" lang="zh-CHS" style="color: #0000cc; ">获取源</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Add_the_Framework_to_Your_Project" target="_top" lang="zh-CHS" style="color: #0000cc; ">向项目中添加框架</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Make_a_Test_Target" target="_top" lang="zh-CHS" style="color: #0000cc; ">使测试目标</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Set_Up_the_Executable_Run_Environment" target="_top" lang="zh-CHS" style="color: #0000cc; ">设置可执行文件运行环境</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Build_and_Go" target="_top" lang="zh-CHS" style="color: #0000cc; ">生成并转</a></li><li style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_XcodeGuide%23Summary" target="_top" lang="zh-CHS" style="color: #0000cc; ">摘要</a></li></ul><p style="line-height: 1.25em; max-width: 64em; "></p><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">本指南将介绍如何在 Mac OS X 上的 Xcode 项目中使用谷歌测试框架。</font><font lang="zh-CHS">本教程开始快速解释为有经验的用户做什么。</font><font lang="zh-CHS">快速起步后指南 》 都提供了进一步的解释每个步骤。</font></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Quick_Start" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">快速入门</font></h1><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">这是快速指南在 Xcode 项目中使用谷歌测试。</p><ol style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><font lang="zh-CHS">使用此命令在<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest" rel="nofollow" target="_top" style="color: #0000cc; ">网站</a>下载源代码：&nbsp;<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn 签出 http://googletest.googlecode.com/svn/trunk/ googletest 只读</tt></font></li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">开放中的<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">gtest.xcodeproj</tt>&nbsp;<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">googletest-读-只/xcode/</tt>目录并生成 gtest.framework。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">名为"UnitTests"类似 Xcode 项目中创建一个新的"壳工具"目标</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">将 gtest.framework 添加到您的项目，并将其添加到"UnitTests"的"链接二进制与图书馆"生成阶段</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">添加您的单元测试的源代码以"UnitTests"的"编译来源"生成阶段</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">编辑"UnitTests"可执行文件并添加环境变量命名为"DYLD_FRAMEWORK_PATH"值等于框架包含 gtest.framework 相对于已编译的可执行文件的路径。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; ">生成并转</li></ol><font lang="zh-CHS">以下各节进一步解释每个深度，更详细地描述了如何完成它包括一些变化在上面列出的步骤。</font><p style="line-height: 1.25em; max-width: 64em; "></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Get_the_Source" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">获取源</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">目前，此处讨论的 gtest.framework 标记的谷歌测试版本中不可用，只有在树干。</font><font lang="zh-CHS">解释在谷歌测试<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout%2522%253Esvn" rel="nofollow" target="_top" style="color: #0000cc; ">网站</a>，你可以得到代码从匿名 SVN 使用此命令：</font></p><pre class="prettyprint" style="font-size: 12px; padding-top: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em; padding-left: 0.5em; overflow-x: auto; overflow-y: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee; "><span class="pln" style="color: #000000; ">svn checkout http</span><span class="pun" style="color: #666600; ">:</span><span class="com" style="color: #880000; ">//googletest.googlecode.com/svn/trunk/ googletest-read-only</span></pre><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">或者，如果您正在使用颠覆您自己的代码库中，可以添加 Google Test 作为外部相关性颠覆资料库。</font><font lang="zh-CHS">按照这种方法，签出 svn 存储库，所有人都还将收到一份 Google 测试 （特定的版本，如果您愿意） 而不必显式签出。</font><font lang="zh-CHS">这一组的组成项目简单并减少复制到存储库中的代码。</font></p><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">若要使用<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn:externals</tt>，决定要将具有外部源驻留。</font><font lang="zh-CHS">因为你想要分支的一部分进行发布时，您可以选择把树干内, 外部源。</font><font lang="zh-CHS">然而，把它称为<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">third-party/googletest/1.0.1</tt>类似的版本标记的目录中的树干以外，是另一种选择。</font><font lang="zh-CHS">一旦建立了位置，则使用<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn propedit svn:externals _directory_</tt>&nbsp;svn:externals 属性设置对存储库中的目录。</font><font lang="zh-CHS">此目录不能包含的代码，但它的版本控制的父目录。</font></p><p style="line-height: 1.25em; max-width: 64em; "><font><font lang="zh-CHS">命令<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn propedit</tt>将会出现你颠覆编辑器中，使编辑更简单长，（可能多行） 的属性。</font><font lang="zh-CHS">这同一种方法可用于检查出标记的分支，通过使用相应的 URL （例如<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">http://googletest.googlecode.com/svn/tags/release-1.0.1</tt>）。</font><font lang="zh-CHS">另外，svn:externals 属性允许的特定修订版的树干与规范<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">-r_ # # _</tt>选项 （例如<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">的外部对象/src/googletest-r60 http://googletest.googlecode.com/svn/trunk</tt></font></font>).</p><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">这里是一个项目 (阅读通过<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">svn propget</tt>) 树干上使用 svn:externals 属性的示例。</font><font lang="zh-CHS">此值将签出到谷歌测试的副本<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">主干/外部对象/src/googletest/</tt>目录。</font></p><pre class="prettyprint" style="font-size: 12px; padding-top: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em; padding-left: 0.5em; overflow-x: auto; overflow-y: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee; "><span class="pun" style="color: #666600; ">[</span><span class="typ" style="color: #660066; ">Computer</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; ">svn</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> user$ svn propget svn</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; ">externals trunk<br />externals</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">src</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">googletest http</span><span class="pun" style="color: #666600; ">:</span><span class="com" style="color: #880000; ">//googletest.googlecode.com/svn/trunk</span></pre><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Add_the_Framework_to_Your_Project" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">向项目中添加框架</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">下一步是建立并将 gtest.framework 添加到您自己的项目。</font><font lang="zh-CHS">本指南描述了下面的两种常用方法。</font></p><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><font lang="zh-CHS"><strong>选项 1</strong>&nbsp;---将谷歌测试添加到您自己的项目，最简单的方法就是打开 gtest.xcodeproj (xcode 中发现谷歌测试树干的目录） 和手动构建框架。</font><font lang="zh-CHS">然后，将生成的框架添加到您的项目使用"添加-&gt; 现有框架 &#8230; &#8230;"从上下文菜单或"项目-&gt; 添加..."从主菜单。</font><font lang="zh-CHS">Gtest.framework 是可重定位，并包含页眉和您需要进行测试的目标代码。</font><font lang="zh-CHS">此方法要求重建每次您升级谷歌测试您的项目中。</font></li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS"><strong>选项 2</strong>&nbsp;---如果您打算将为生的谷歌测试树干，其最新的功能纳入您的单元测试 （或自己是谷歌测试开发人员）。</font><font lang="zh-CHS">你要重建框架，每次更新源。</font><font lang="zh-CHS">要这样做，您需要将 gtest.xcodeproj 文件，框架本身，添加到您自己 Xcode 项目。</font><font lang="zh-CHS">然后，从生成产品项目的三角形发现，您可以找到 gtest.framework，可以添加到你的目标 （以下讨论）。</font></li></ul><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Make_a_Test_Target" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">使测试目标</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">要开始编写测试，使新的"壳工具"目标。</font><font lang="zh-CHS">此目标模板是 BSD、 可可、 或碳下可用。</font><font lang="zh-CHS">添加您的单元测试的目标"编译来源"生成阶段的源代码。</font></p><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">接下来，你要在两种不同方法中添加 gtest.framework，取决于哪个选项您选择以上。</p><ul style="padding-left: 25px; max-width: 62em; "><li style="margin-bottom: 0.3em; "><font lang="zh-CHS"><strong>选项 1</strong>&nbsp;---在编译期间，Xcode 将需要知道您要链接对 gtest.framework。</font><font lang="zh-CHS">将 gtest.framework 添加到您的测试目标的"链接二进制与图书馆"生成阶段。</font><font lang="zh-CHS">这将包括谷歌测试头在标题搜索路径中，并将告诉链接器在哪里可以找到的库。</font></li><li style="margin-bottom: 0.3em; "><font lang="zh-CHS"><strong>选项 2</strong>&nbsp;---如果您工作的树干，你也要将 gtest.framework 添加到您的测试目标的你"链接二进制与图书馆"生成阶段。</font><font lang="zh-CHS">此外，你要将 gtest.framework 作为依赖项添加到你的单元测试目标。</font><font lang="zh-CHS">这种方式，Xcode 将确保该 gtest.framework 是到目前为止，每次您的构建你的目标。</font><font lang="zh-CHS">最后，如果你不使用谷歌测试共享生成目录，你得将 gtest.framework 复制到您自己生成产品目录，使用"运行脚本"生成阶段。</font></li></ul><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Set_Up_the_Executable_Run_Environment" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">设置可执行文件运行环境</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">可执行单元测试是壳的工具，因为它没有一捆，<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">内容/框架</tt>的目录，在其中放置 gtest.framework。</font><font lang="zh-CHS">相反，必须在运行时告诉动态链接器搜索中的另一个位置的框架。</font><font lang="zh-CHS">这可以通过在"编辑活动的可执行文件..."中设置的"DYLD_FRAMEWORK_PATH"的环境变量</font><font lang="zh-CHS">参数选项卡，在"设置环境变量："。</font><font lang="zh-CHS">此值的路径是目录的包含 gtest.framework 的路径 （相对或绝对）。</font></p><p lang="zh-CHS" style="line-height: 1.25em; max-width: 64em; ">如果您还没有设置 DYLD_FRAMEWORK_PATH，正确，可能会得到这样一条消息：</p><pre class="prettyprint" style="font-size: 12px; padding-top: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em; padding-left: 0.5em; overflow-x: auto; overflow-y: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee; "><span class="pun" style="color: #666600; ">[</span><span class="typ" style="color: #660066; ">Session</span><span class="pln" style="color: #000000; "> started at </span><span class="lit" style="color: #006666; ">2008</span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">08</span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">15</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">06</span><span class="pun" style="color: #666600; ">:</span><span class="lit" style="color: #006666; ">23</span><span class="pun" style="color: #666600; ">:</span><span class="lit" style="color: #006666; ">57</span><span class="pln" style="color: #000000; "> </span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">0600.</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "><br />&nbsp; dyld</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">Library</span><span class="pln" style="color: #000000; "> </span><span class="kwd" style="color: #000088; ">not</span><span class="pln" style="color: #000000; "> loaded</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">@loader_path</span><span class="pun" style="color: #666600; ">/../</span><span class="typ" style="color: #660066; ">Frameworks</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">gtest</span><span class="pun" style="color: #666600; ">.</span><span class="pln" style="color: #000000; ">framework</span><span class="pun" style="color: #666600; ">/</span><span class="typ" style="color: #660066; ">Versions</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">A</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">gtest<br />&nbsp; &nbsp; </span><span class="typ" style="color: #660066; ">Referenced</span><span class="pln" style="color: #000000; "> </span><span class="kwd" style="color: #000088; ">from</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; "> </span><span class="str" style="color: #008800; ">/Users/</span><span class="pln" style="color: #000000; ">username</span><span class="pun" style="color: #666600; ">/</span><span class="typ" style="color: #660066; ">Documents</span><span class="pun" style="color: #666600; ">/</span><span class="typ" style="color: #660066; ">Sandbox</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">gtestSample</span><span class="pun" style="color: #666600; ">/</span><span class="pln" style="color: #000000; ">build</span><span class="pun" style="color: #666600; ">/</span><span class="typ" style="color: #660066; ">Debug</span><span class="pun" style="color: #666600; ">/</span><span class="typ" style="color: #660066; ">WidgetFrameworkTest</span><span class="pln" style="color: #000000; "><br />&nbsp; &nbsp; </span><span class="typ" style="color: #660066; ">Reason</span><span class="pun" style="color: #666600; ">:</span><span class="pln" style="color: #000000; "> image </span><span class="kwd" style="color: #000088; ">not</span><span class="pln" style="color: #000000; "> found</span></pre><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">要正确这个问题，必须包含可执行文件中指定的目录"从引用："上述错误消息中的值。</font><font lang="zh-CHS">然后，在此位置的终端，发现包含 gtest.framework 的目录的相对路径。</font><font lang="zh-CHS">这就是你需要设置为 DYLD_FRAMEWORK_PATH 的值。</font></p><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Build_and_Go" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">生成并转</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">现在，当您单击"生成走"，将会执行测试。</font><font lang="zh-CHS">倾倒出这样的事：</font></p><pre class="prettyprint" style="font-size: 12px; padding-top: 0.5em; padding-right: 0.5em; padding-bottom: 0.5em; padding-left: 0.5em; overflow-x: auto; overflow-y: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee; "><span class="pun" style="color: #666600; ">[</span><span class="typ" style="color: #660066; ">Session</span><span class="pln" style="color: #000000; "> started at </span><span class="lit" style="color: #006666; ">2008</span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">08</span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">06</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">06</span><span class="pun" style="color: #666600; ">:</span><span class="lit" style="color: #006666; ">36</span><span class="pun" style="color: #666600; ">:</span><span class="lit" style="color: #006666; ">13</span><span class="pln" style="color: #000000; "> </span><span class="pun" style="color: #666600; ">-</span><span class="lit" style="color: #006666; ">0600.</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[==========]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">Running</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">2</span><span class="pln" style="color: #000000; "> tests </span><span class="kwd" style="color: #000088; ">from</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">1</span><span class="pln" style="color: #000000; "> test </span><span class="kwd" style="color: #000088; ">case</span><span class="pun" style="color: #666600; ">.</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[----------]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">Global</span><span class="pln" style="color: #000000; "> test environment </span><span class="kwd" style="color: #000088; ">set</span><span class="pun" style="color: #666600; ">-</span><span class="pln" style="color: #000000; ">up</span><span class="pun" style="color: #666600; ">.</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[----------]</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">2</span><span class="pln" style="color: #000000; "> tests </span><span class="kwd" style="color: #000088; ">from</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">WidgetInitializerTest</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[</span><span class="pln" style="color: #000000; "> RUN &nbsp; &nbsp; &nbsp;</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">WidgetInitializerTest</span><span class="pun" style="color: #666600; ">.</span><span class="typ" style="color: #660066; ">TestConstructor</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[</span><span class="pln" style="color: #000000; "> &nbsp; &nbsp; &nbsp; OK </span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">WidgetInitializerTest</span><span class="pun" style="color: #666600; ">.</span><span class="typ" style="color: #660066; ">TestConstructor</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[</span><span class="pln" style="color: #000000; "> RUN &nbsp; &nbsp; &nbsp;</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">WidgetInitializerTest</span><span class="pun" style="color: #666600; ">.</span><span class="typ" style="color: #660066; ">TestConversion</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[</span><span class="pln" style="color: #000000; "> &nbsp; &nbsp; &nbsp; OK </span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">WidgetInitializerTest</span><span class="pun" style="color: #666600; ">.</span><span class="typ" style="color: #660066; ">TestConversion</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[----------]</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">Global</span><span class="pln" style="color: #000000; "> test environment tear</span><span class="pun" style="color: #666600; ">-</span><span class="pln" style="color: #000000; ">down<br /></span><span class="pun" style="color: #666600; ">[==========]</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">2</span><span class="pln" style="color: #000000; "> tests </span><span class="kwd" style="color: #000088; ">from</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">1</span><span class="pln" style="color: #000000; "> test </span><span class="kwd" style="color: #000088; ">case</span><span class="pln" style="color: #000000; "> ran</span><span class="pun" style="color: #666600; ">.</span><span class="pln" style="color: #000000; "><br /></span><span class="pun" style="color: #666600; ">[</span><span class="pln" style="color: #000000; "> &nbsp;PASSED &nbsp;</span><span class="pun" style="color: #666600; ">]</span><span class="pln" style="color: #000000; "> </span><span class="lit" style="color: #006666; ">2</span><span class="pln" style="color: #000000; "> tests</span><span class="pun" style="color: #666600; ">.</span><span class="pln" style="color: #000000; "><br /><br /></span><span class="typ" style="color: #660066; ">The</span><span class="pln" style="color: #000000; "> </span><span class="typ" style="color: #660066; ">Debugger</span><span class="pln" style="color: #000000; "> has exited </span><span class="kwd" style="color: #000088; ">with</span><span class="pln" style="color: #000000; "> status </span><span class="lit" style="color: #006666; ">0.</span><span class="pln" style="color: #000000; "> &nbsp;</span></pre><h1 style="font-size: x-large; margin-top: 0px; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-left: 0px; max-width: 700px; background-position: initial initial; background-repeat: initial initial; "><a name="Summary" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a><font lang="zh-CHS">摘要</font></h1><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">单元测试是有价值的方式，确保你的数据模型保持有效，即使在快速发展过程中或重构。</font><font lang="zh-CHS">谷歌测试框架是伟大单元测试框架，C 和 c + + 于一体的与 Xcode 开发环境很好。</font></p></div></div></td></tr><tr></tr></tbody></table></div><form name="delcom" action="http://code.google.com/p/googletest/w/delComment.do" method="POST" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></form></div><div id="footer" dir="ltr" style="clear: both; text-align: center; margin-top: 3.5em; margin-bottom: 1em; height: 53px; background-position: 0% 50%; background-repeat: no-repeat no-repeat; "><div class="text" style="padding-top: 20px; "><font lang="zh-CHS">&#169; 2011 Google--<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fwww.google.com%2Fprivacy.html" target="_top" style="color: #0000cc; ">私隐</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2Fterms.html" target="_top" style="color: #0000cc; ">条款</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fsupport%2F" target="_top" style="color: #0000cc; ">项目主办的帮助</a></font></div></div><div class="hostedBy" style="text-align: center; margin-top: -20px; "><span lang="zh-CHS" style="vertical-align: top; ">通过<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2F" target="_top" style="color: #0000cc; ">Google 计划主办</a>动力</span></div></div></span><img src ="http://www.cppblog.com/lauer3912/aggbug/156882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:48 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>V1_6_AdvancedGuide   关于使用谷歌 c + + 测试框架的高级的主题</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156881.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156881.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156881.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156881.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我的收藏夹&nbsp;&#9660;&nbsp;|登录googletest谷歌 c + + 测试框架&nbsp;项目主页下载维基问题源搜索&nbsp;&nbsp; 内搜索：&nbsp;&nbsp; &nbsp;所有 wiki 页面&nbsp; 特色的页&nbsp; 当前页&nbsp; &nbsp;&nbsp; &nbsp;不推荐使用的页&nbsp;&nbsp; &nbsp;&nbsp;对于&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/lauer3912/archive/2011/09/26/156881.html'>阅读全文</a><img src ="http://www.cppblog.com/lauer3912/aggbug/156881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:41 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>V1_6_Samples   谷歌 c + + 测试框架样本</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156879.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:30:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156879.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156879.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156879.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156879.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: Simsun; line-height: normal; font-size: medium; "><div style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; font: normal normal normal 82%/normal arial, sans-serif; margin-top: 3px; margin-right: 0px; margin-bottom: 3px; margin-left: 0px; min-width: 768px; background-position: initial initial; background-repeat: initial initial; "><div class="headbg" style="margin-top: 0px; margin-right: 8px; margin-bottom: 0px; margin-left: 8px; "><div id="gaia" style="text-align: right; margin-bottom: 10px; "><span><font><font lang="zh-CHS"><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_Samples%23" id="projects-dropdown" target="_top" style="color: #0000cc; text-decoration: none; "><u>我的收藏夹</u>&nbsp;<small>&#9660;</small>&nbsp;</a>|</font><font lang="zh-CHS"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_Samples&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fwiki%2FV1_6_Samples" target="_top" style="color: #0000cc; text-decoration: none; "><u>登录</u></a></font></font></span></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; left: 0pt; "></div><div class="gbh" style="font-size: 1px; height: 0px; position: absolute; top: 24px; width: 663px; right: 0pt; "></div><div style="height: 1px; "></div><table cellpadding="0" cellspacing="0" itemscope="" itemtype="http://schema.org/CreativeWork" style="border-collapse: separate; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; width: 752px; "><tbody><tr style="height: 58px; "><td id="plogo" style="width: 55px; text-align: center; vertical-align: bottom; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #0000cc; "><img src="http://www.gstatic.com/codesite/ph/images/search-48.gif" alt="Logo" itemprop="image" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; " /></a></td><td style="padding-left: 0.5em; "><div id="pname" style="font-size: 39px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #666666; text-decoration: none; "><span itemprop="name" lang="zh-CHS">googletest</span></a></div><div id="psum"><a id="project_summary_link" href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" target="_top" style="color: #444444; text-decoration: none; "><span itemprop="description" lang="zh-CHS">谷歌 c + + 测试框架</span></a></div></td><td style="white-space: nowrap; text-align: right; vertical-align: bottom; "><form action="http://www.microsofttranslator.com/bv.aspx" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><input size="30" name="q" value="" type="text" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " />&nbsp;<input type="submit" name="projectsearch" value="Search projects" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></td></tr></tbody></table></div><div id="mt" class="gtb" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ebeff9; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #6b90da; padding-top: 5px; padding-right: 10px; padding-left: 5px; white-space: nowrap; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2F" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">项目主页</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fdownloads%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">下载</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fw%2Flist" class="tab active" target="_top" lang="zh-CHS" style="color: #000000; cursor: default; float: left; margin-top: 0px; margin-right: 5px; margin-bottom: -1px; margin-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; border-top-width: 1px; border-right-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-left-style: solid; border-top-color: #6b90da; border-right-color: #6b90da; border-left-color: #6b90da; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; font-weight: bold; padding-top: 5px; padding-right: 9px; padding-bottom: 6px; padding-left: 9px; text-decoration: none; background-position: initial initial; background-repeat: initial initial; ">维基</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fissues%2Flist" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">问题</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fcheckout" class="tab " target="_top" lang="zh-CHS" style="color: #0000cc; cursor: pointer; float: left; margin-top: 5px; margin-right: 15px; margin-bottom: 6px; margin-left: 10px; ">源</a><div class="gtbc" style="clear: left; "></div></div><table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st" style="border-collapse: separate; "><tbody><tr><td class="subt" style="background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ffffff), to(#f1f1f1)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; border-bottom-style: solid; border-bottom-color: #cccccc; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 14px; height: 33px; "><div class="issueDetail"><div class="isf"><span class="inIssueList"><span lang="zh-CHS">搜索</span>&nbsp;<form action="http://www.microsofttranslator.com/bv.aspx" method="GET" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; display: inline; "><select id="can" name="can" style="font-family: arial, sans-serif; ">&nbsp; <option disabled="disabled">内搜索：</option>&nbsp;&nbsp; &nbsp;<option value="1">所有 wiki 页面</option>&nbsp; <option value="3">特色的页</option>&nbsp; <option value="2" selected="selected">当前页</option>&nbsp; &nbsp;&nbsp; &nbsp;<option value="4">不推荐使用的页</option>&nbsp;&nbsp; &nbsp;</select>&nbsp;<span lang="zh-CHS">对于</span>&nbsp;<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" style="font-family: arial, sans-serif; padding-left: 1px; padding-right: 1px; border-top-color: #999999; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; padding-top: 2px; padding-bottom: 2px; " /></span>&nbsp;<input type="submit" value="Search" style="font-family: arial, sans-serif; padding-left: 3px; padding-right: 3px; font-size: 13px; background-image: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#f9f9f9), to(#e3e3e3)); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; vertical-align: baseline; padding-top: 1px; padding-bottom: 1px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-right-color: #aaaaaa; border-left-color: #aaaaaa; border-top-color: #cccccc; border-bottom-color: #888888; border-top-left-radius: 3px 3px; border-top-right-radius: 3px 3px; border-bottom-right-radius: 3px 3px; border-bottom-left-radius: 3px 3px; cursor: pointer; text-decoration: none; background-position: initial initial; background-repeat: initial initial; " /></form></span></div></div></td><td align="right" valign="top" class="bevel-right" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></td></tr></tbody></table><div id="maincol" style="padding-right: 3px; padding-left: 3px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #ffffff; "><div id="wikipage" style="background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: #f8f8f8; padding-bottom: 10px; background-position: initial initial; background-repeat: initial initial; "><table style="border-collapse: separate; "><tbody><tr><td style="vertical-align: top; padding-left: 5px; "><div id="wikiheader" style="padding-top: 10px; margin-bottom: 12px; "><span lang="zh-CHS" style="font-size: 16px; font-weight: bold; ">V1_6_Samples</span>&nbsp;&nbsp;<div><em lang="zh-CHS">谷歌 c + + 测试框架样本</em><div id="wikiauthor" style="clear: both; text-align: right; font-size: x-small; float: right; "><font lang="zh-CHS">由<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fu%2F%40VBNWR1RSBxdEWgZ0%2F" target="_top" style="color: #0000cc; white-space: nowrap; ">zhanyong...@gmail.com</a>更新的<span title="Mon Apr 18 14:45:17 2011">2011 年 4 月 18 日</span></font></div></div></div><div id="wikicontent"><div class="vt" id="wikimaincol" style="vertical-align: top; padding-top: 5px; padding-right: 25px; padding-bottom: 10px; padding-left: 10px; background-color: #ffffff; min-width: 64em; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; "><p style="line-height: 1.25em; max-width: 64em; "><font lang="zh-CHS">如果你想和我们一样，你想看一些谷歌测试示例代码。</font><font lang="zh-CHS"><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2F%23svn%2Ftrunk%2Fsamples" rel="nofollow" target="_top" style="color: #0000cc; ">Samples 文件夹</a>具有大量注释示例演示了如何使用各种谷歌测试功能。</font></p><ul style="padding-left: 25px; max-width: 62em; "><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample1_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 1</a>显示了使用谷歌测试来测试 c + + 函数的基本步骤。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample2_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 2</a>显示了一类具有多个成员函数更复杂的单元测试。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample3_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 3</a>使用测试夹具。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample4_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 4</a>置于基准测试夹具、 共享测试逻辑和派生夹具中重新使用它。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample5_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 5</a>教如何通过从它派生 sub-fixtures 重用测试夹具在多个测试用例。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample6_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; "># 6 示例</a>演示类型参数测试。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample7_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 7</a>教值参数测试的基本知识。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample8_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 8</a>显示值参数测试中使用<tt style="font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; font-size: 12px; max-width: 66em; ">Combine()</tt>&nbsp;。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample9_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 9</a>显示了使用 API 修改 Google 测试控制台输出的侦听器和检查测试结果及其反射 API 的使用。</li><li lang="zh-CHS" style="margin-bottom: 0.3em; "><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fgoogletest%2Fsource%2Fbrowse%2Ftrunk%2Fsamples%2Fsample10_unittest.cc" rel="nofollow" target="_top" style="color: #0000cc; ">示例 # 10</a>显示侦听器的 API 来实现原始内存泄漏检测器的使用。</li></ul></div></div></td></tr><tr></tr></tbody></table></div><form name="delcom" action="http://code.google.com/p/googletest/w/delComment.do" method="POST" target="_top" style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "></form></div><div id="footer" dir="ltr" style="clear: both; text-align: center; margin-top: 3.5em; margin-bottom: 1em; height: 53px; background-position: 0% 50%; background-repeat: no-repeat no-repeat; "><div class="text" style="padding-top: 20px; "><font lang="zh-CHS">&#169; 2011 Google--<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fwww.google.com%2Fprivacy.html" target="_top" style="color: #0000cc; ">私隐</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2Fterms.html" target="_top" style="color: #0000cc; ">条款</a><a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fp%2Fsupport%2F" target="_top" style="color: #0000cc; ">项目主办的帮助</a></font></div></div><div class="hostedBy" style="text-align: center; margin-top: -20px; "><span lang="zh-CHS" style="vertical-align: top; ">通过<a href="http://www.microsofttranslator.com/bv.aspx?from=&amp;to=zh-CHS&amp;a=http%3A%2F%2Fcode.google.com%2Fprojecthosting%2F" target="_top" style="color: #0000cc; ">Google 计划主办</a>动力</span></div></div></span><img src ="http://www.cppblog.com/lauer3912/aggbug/156879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:30 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>V1_6_Primer   入门谷歌 c + + 测试框架</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/26/156878.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 26 Sep 2011 12:28:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/26/156878.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156878.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/26/156878.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156878.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156878.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我的收藏夹&nbsp;&#9660;&nbsp;|登录googletest谷歌 c + + 测试框架&nbsp;项目主页下载维基问题源搜索&nbsp;&nbsp; 内搜索：&nbsp;&nbsp; &nbsp;所有 wiki 页面&nbsp; 特色的页&nbsp; 当前页&nbsp; &nbsp;&nbsp; &nbsp;不推荐使用的页&nbsp;&nbsp; &nbsp;&nbsp;对于&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/lauer3912/archive/2011/09/26/156878.html'>阅读全文</a><img src ="http://www.cppblog.com/lauer3912/aggbug/156878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-26 20:28 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/26/156878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google C++ Testing Framework简介</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/19/156261.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Mon, 19 Sep 2011 13:03:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/19/156261.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/156261.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/19/156261.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/156261.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/156261.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="font-family: verdana, sans-serif; font-size: 12px; line-height: 18px; background-color: #f8fafd; "><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>简介：</strong>&nbsp;Google 提供一种用于为 C/C++ 软件开发单元测试的开放源码框架，它很有意思，也很容易使用。本文介绍一些比较有用的 Google C++ Testing Framework 特性。本文基于 version 1.4。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>为什么要使用 Google C++ Testing Framework？</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">使用这个框架有许多好理由。本节讨论其中几个。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">某些类型的测试有糟糕的内存问题，这些问题只在某几次运行期间出现。Google 的测试框架为处理这种情况提供了出色的支持。可以使用 Google 框架重复运行相同的测试一千次。当出现故障的迹象时，自动地调用调试器。另外，这只需要在命令行上传递两个开关即可实现：--gtest_repeat=1000 --gtest_break_on_failure。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">与其他许多测试框架相反，可以把 Google 测试框架内置的断言部署在禁用了异常处理（通常由于性能原因）的软件中。因此，也可以在析构函数中安全地使用断言。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">运行测试很简单。只需调用预定义的 RUN_ALL_TESTS 宏，而不需要通过创建或驱动单独的运行器类来执行测试。这比 CppUnit 等框架方便多了。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">只需传递一个开关即可生成 Extensible Markup Language (XML) 报告： --gtest_output="xml:&lt;file name&gt;"。在 CppUnit 和 CppTest 等框架中，需要编写很多代码才能生成 XML 输出。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">创建基本测试</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">请考虑 清单 1 所示的平方根函数的原型。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 1. 平方根函数的原型</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">double square-root (const double);</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">对于负数，这个例程返回 -1。正数测试和负数测试对它都有意义，所以我们编写两个测试。清单 2 给出测试用例。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 2. 平方根函数的单元测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">#include "gtest/gtest.h"</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (SquareRootTest, PositiveNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (18.0, square-root (324.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (25.4, square-root (645.16));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (50.3321, square-root (2533.310224));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (SquareRootTest, ZeroAndNegativeNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EQ (0.0, square-root (0.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EQ (-1, square-root (-22.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">清单 2 创建一个名为 SquareRootTest 的测试层次结构，然后在其中添加两个单元测试 PositiveNos 和 ZeroAndNegativeNos。TEST 是在 gtest.h（可以在下载的源代码中找到）中定义的预定义宏，它帮助定义这个层次结构。EXPECT_EQ 和 ASSERT_EQ 也是宏 &#8212; 对于前者，即使出现测试失败，测试仍然继续执行；对于后者，测试终止执行。显然，如果 0 的平方根是除 0 之外的任何数字，就没必要再执行测试了。因此，ZeroAndNegativeNos 测试只使用 ASSERT_EQ，而 PositiveNos 测试使用 EXPECT_EQ，来报告存在多少个测试用例是平方根函数失败而不终止测试的情况。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>运行第一个测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">既然已经创建了第一个基本测试，现在就该运行它了。清单 3 是运行测试的主例程。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 3. 运行平方根测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">#include "gtest/gtest.h"</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST(SquareRootTest, PositiveNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (18.0, square-root (324.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (25.4, square-root (645.16));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (50.3321, square-root (2533.310224));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (SquareRootTest, ZeroAndNegativeNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EQ (0.0, square-root (0.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EQ (-1, square-root (-22.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">int main(int argc, char **argv) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">::testing::InitGoogleTest(&amp;argc, argv);</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">return RUN_ALL_TESTS();</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">顾名思义，::testing::InitGoogleTest 方法的作用就是对框架进行初始化，必须在调用 RUN_ALL_TESTS 之前调用它。在代码中只能调用 RUN_ALL_TESTS 一次，因为多次调用会与框架的一些高级特性冲突，不支持这种做法。注意，RUN_ALL_TESTS 自动地探测并运行用 TEST 宏定义的所有测试。在默认情况下，结果输出到标准输出。清单 4 给出输出。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 4. 运行平方根测试的输出</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Running main() from user_main.cpp</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] Running 2 tests from 1 test case.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment set-up.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 2 tests from SquareRootTest</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ RUN ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">..\user_sqrt.cpp(6862): error: Value of: sqrt (2533.310224)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Actual: 50.332</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Expected: 50.3321</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos (9 ms)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ RUN ] SquareRootTest.ZeroAndNegativeNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ OK ] SquareRootTest.ZeroAndNegativeNos (0 ms)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 2 tests from SquareRootTest (0 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment tear-down</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] 2 tests from 1 test case ran. (10 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ PASSED ] 1 test.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] 1 test, listed below:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">1 FAILED TEST</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>Google C++ Testing Framework 的选项</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">在 清单 3 中，InitGoogleTest 函数接受测试基础设施的参数。本节讨论可以通过测试框架的参数实现的一些功能。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">通过在命令行上传递 --gtest_output="xml:report.xml"，可以把输出转储为 XML 格式。当然，可以把 report.xml 替换为您喜欢的任何文件名。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">某些测试有时候会失败，但是在大多数时候会顺利通过。这是与内存损坏相关的问题的典型特点。如果多次运行测试，就能够提高发现失败的可能性。如果在命令行上传递 --gtest_repeat=2 --gtest_break_on_failure，就重复运行相同的测试两次。如果测试失败，会自动调用调试器。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">并不需要每次都运行所有测试，尤其是在修改的代码只影响某几个模块的情况下。为了支持运行一部分测试，Google 提供 --gtest_filter=&lt;test string&gt;。test string 的格式是由冒号 (:) 分隔的一系列通配符模式。例如，--gtest_filter=* 运行所有测试，而 --gtest_filter=SquareRoot* 只运行 SquareRootTest 测试。如果希望只运行 SquareRootTest 中的正数单元测试，应该使用 --gtest_filter=SquareRootTest.*-SquareRootTest.Zero*。注意，SquareRootTest.* 表示属于 SquareRootTest 的所有测试，而 -SquareRootTest.Zero* 表示不运行名称以 Zero 开头的测试。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">清单 5 中的示例用 gtest_output、gtest_repeat 和 gtest_filter 选项运行 SquareRootTest。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 5. 用 gtest_output、gtest_repeat 和 gtest_filter 选项运行 SquareRootTest</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[arpan@tintin] ./test_executable --gtest_output="xml:report.xml" --gtest_repeat=2 --</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">gtest_filter=SquareRootTest.*-SquareRootTest.Zero*</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Repeating all tests (iteration 1) . . .</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Note: Google Test filter = SquareRootTest.*-SquareRootTest.Z*</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] Running 1 test from 1 test case.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment set-up.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from SquareRootTest</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ RUN ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">..\user_sqrt.cpp (6854): error: Value of: sqrt (2533.310224)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Actual: 50.332</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Expected: 50.3321</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos (2 ms)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from SquareRootTest (2 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment tear-down</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] 1 test from 1 test case ran. (20 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ PASSED ] 0 tests.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] 1 test, listed below:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">1 FAILED TEST</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Repeating all tests (iteration 2) . . .</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Note: Google Test filter = SquareRootTest.*-SquareRootTest.Z*</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] Running 1 test from 1 test case.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment set-up.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from SquareRootTest</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ RUN ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">..\user_sqrt.cpp (6854): error: Value of: sqrt (2533.310224)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Actual: 50.332</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Expected: 50.3321</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos (2 ms)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from SquareRootTest (2 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] Global test environment tear-down</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[==========] 1 test from 1 test case ran. (20 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ PASSED ] 0 tests.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] 1 test, listed below:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">1 FAILED TEST</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>临时禁用测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">可以临时禁用测试吗？可以，只需在逻辑测试名或单元测试名前面加上 DISABLE_ 前缀，它就不会执行了。清单 6 演示如何禁用 清单 2 中的 PositiveNos 测试。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 6. 临时禁用测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">#include "gtest/gtest.h"</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (DISABLE_SquareRootTest, PositiveNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (18.0, square-root (324.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (25.4, square-root (645.16));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (50.3321, square-root (2533.310224));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">OR</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (SquareRootTest, DISABLE_PositiveNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (18.0, square-root (324.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (25.4, square-root (645.16));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_EQ (50.3321, square-root (2533.310224));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">注意，如果禁用了任何测试，Google 框架会在测试执行结束时输出警告消息，见 清单 7。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 7. Google 警告用户在框架中有禁用的测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">1 FAILED TEST</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">YOU HAVE 1 DISABLED TEST</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">如果希望继续运行禁用的测试，那么在命令行上传递 -gtest_also_run_disabled_tests 选项。清单 8 给出运行 DISABLE_PositiveNos 测试时的输出。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 8. Google 允许运行已经禁用的测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from DISABLED_SquareRootTest</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ RUN ] DISABLED_SquareRootTest.PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">..\user_sqrt.cpp(6854): error: Value of: square-root (2533.310224)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Actual: 50.332</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Expected: 50.3321</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] DISABLED_SquareRootTest.PositiveNos (2 ms)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[----------] 1 test from DISABLED_SquareRootTest (2 ms total)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] 1 tests, listed below:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">[ FAILED ] SquareRootTest. PositiveNos</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>断言</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Google 测试框架提供一整套预定义的断言。断言分为两类 &#8212; 名称以 ASSERT_ 开头的断言和名称以 EXPECT_ 开头的断言。如果一个断言失败，ASSERT_* 断言会终止程序执行，而 EXPECT_* 断言继续运行。当断言失败时，这两者都输出文件名、行号和可定制的消息。比较简单的断言包括 ASSERT_TRUE (condition) 和 ASSERT_NE (val1, val2)。前者期望条件总是成立，而后者期望两个值不匹配。这些断言也适用于用户定义的类型，但是必须覆盖相应的比较操作符（==、!=、&lt;= 等等）。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>浮点数比较</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Google 提供 清单 9 所示的宏以支持浮点数比较。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 9. 用于浮点数比较的宏</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_FLOAT_EQ (expected, actual)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_DOUBLE_EQ (expected, actual)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_NEAR (expected, actual, absolute_range)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_FLOAT_EQ (expected, actual)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_DOUBLE_EQ (expected, actual)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">EXPECT_NEAR (expected, actual, absolute_range)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">为什么需要用单独的宏进行浮点数比较？使用 ASSERT_EQ 不行吗？使用 ASSERT_EQ 和相关的宏可能可以，也可能不行，但是使用专门用于浮点数比较的宏更好。通常，不同的中央处理单元 (CPU) 和操作环境以不同的方式存储浮点数，简单地比较期望值和实际值是无效的。例如，ASSERT_FLOAT_EQ (2.00001, 2.000011) 会顺利通过 &#8212; 如果直到小数点后四位都匹配，Google 就不会抛出错误。如果需要更精确的比较，应该使用 ASSERT_NEAR (2.00001, 2.000011, 0.0000001)，就会得到 清单 10 所示的错误。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 10. ASSERT_NEAR 产生的错误消息</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Math.cc(68): error: The difference between 2.00001 and 2.000011 is 1e-006, which exceeds</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">0.0000001, where</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">2.00001 evaluates to 2.00001,</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">2.000011 evaluates to 2.00001, and</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">0.0000001 evaluates to 1e-007.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>死亡测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Google C++ Testing Framework 有一类有趣的断言（ASSERT_DEATH、ASSERT_EXIT 等），它们称为死亡断言。使用这种断言检查在例程的输入错误的情况下是否发出正确的错误消息，或者例程是否退出并返回正确的退出码。例如，在 清单 3 中，当执行 square-root (-22.0) 时应该产生错误消息，程序退出，返回状态应该是 -1 而不是 -1.0。清单 11 使用 ASSERT_EXIT 检查是否是这样。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 11. 使用 Google 框架运行死亡测试</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">#include "gtest/gtest.h"</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">double square-root (double num) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">if (num &lt; 0.0) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">std::cerr &lt;&lt; "Error: Negative Input\n";</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">exit(-1);</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// Code for 0 and +ve numbers follow&#8230;</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST (SquareRootTest, ZeroAndNegativeNos) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EQ (0.0, square-root (0.0));</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EXIT (square-root (-22.0), ::testing::ExitedWithCode(-1), "Error:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Negative Input");</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">int main(int argc, char **argv) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">::testing::InitGoogleTest(&amp;argc, argv);</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">return RUN_ALL_TESTS();</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EXIT 检查函数是否退出并返回正确的退出码（即 exit 或 _exit 例程的参数），对引号中的字符串和函数发送到标准错误的字符串进行比较。注意，错误消息必须发送到 std::cerr 而不是 std::cout。清单 12 给出 ASSERT_DEATH 和 ASSERT_EXIT 的原型。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 12. 死亡断言的原型</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_DEATH(statement, expected_message)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">ASSERT_EXIT(statement, predicate, expected_message)</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Google 提供预定义的谓词 ::testing::ExitedWithCode(exit_code)。只有在程序退出且退出码与谓词中的 exit_code 相同的情况下，这个谓词的结果才是 true。ASSERT_DEATH 比 ASSERT_EXIT 简单；它只检查标准错误中的错误消息是否是用户期望的消息。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>理解测试装备</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">在执行单元测试之前，通常要执行一些定制的初始化。例如，如果希望度量测试的时间/内存占用量，就需要放置一些测试专用代码以度量这些值。这就是装备的用途 &#8212; 它们帮助完成这种定制的测试初始化。清单 13 给出一个装备类的示例。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 13. 测试装备类</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">class myTestFixture1: public ::testing::test {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">public:</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">myTestFixture1( ) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// initialization code here</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">void SetUp( ) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// code here will execute just before the test ensues</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">void TearDown( ) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// code here will be called just after the test completes</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// ok to through exceptions from here if need be</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">~myTestFixture1( ) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// cleanup any pending stuff, but no exceptions allowed</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">// put in any custom data members that you need</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">};</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">这个装备类派生自 gtest.h 中声明的 ::testing::test 类。清单 14 是使用这个装备类的示例。注意，它使用 TEST_F 宏而不是 TEST。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>清单 14. 装备的使用示例</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST_F (myTestFixture1, UnitTest1) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">&#8230;.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">TEST_F (myTestFixture1, UnitTest2) {</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">&#8230;.</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">}</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">在使用装备时，要注意以下几点：</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">可以在构造函数或 SetUp 方法中执行初始化或分配资源。由用户选择具体方式。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">可以在 TearDown 或析构函数例程中释放资源。但是，如果需要异常处理，那么只能在 TearDown 代码中进行，因为从析构函数中抛出异常会导致不确定的结果。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">在以后的版本中，Google 断言宏可能会在平台上抛出异常。因此，为了便于维护，最好在 TearDown 代码中使用断言宏。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">并不跨多个测试使用同一个测试装备。对于每个新的单元测试，框架创建一个新的测试装备。在 清单 14 中，由于要创建两个 myFixture1 对象，所以两次调用 SetUp 例程（请注意使用正确的拼写）。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>结束语</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">本文仅仅触及了 Google C++ Testing Framework 的皮毛。可以从 Google 网站获得关于这个框架的详细信息。对于高级开发人员，我建议阅读 Boost 单元测试框架和 CppUnit 等开放回归框架方面的其他文章。更多信息参见 参考资料。</p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; "><strong>关于作者</strong></p><p style="font-size: 14px; line-height: 25px; text-indent: 25px; ">Arpan Sen 是致力于电子设计自动化行业的软件开发首席工程师。他使用各种 UNIX 版本（包括 Solaris、SunOS、HP-UX、IRIX，以及 Linux 和 Microsoft Windows）已经多年。他热衷于各种软件性能优化技术、图论和并行计算。Arpan 获得了软件系统硕士学位。</p></span><img src ="http://www.cppblog.com/lauer3912/aggbug/156261.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-19 21:03 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/19/156261.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Test Primer ：开始使用Google C++ 测试框架</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/16/155965.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Fri, 16 Sep 2011 13:59:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/16/155965.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/155965.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/16/155965.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/155965.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/155965.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://ray-leex.iteye.com/blog/212024Google C++ Testing Framework Primer&nbsp;翻译：Ray Li&nbsp;(ray.leex@gmail.com)&nbsp;修改日期：2008年7月6日原文参见：http://code.google.com/p/googletest/wiki/GoogleTestPrimer&nbsp...&nbsp;&nbsp;<a href='http://www.cppblog.com/lauer3912/archive/2011/09/16/155965.html'>阅读全文</a><img src ="http://www.cppblog.com/lauer3912/aggbug/155965.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-16 21:59 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/16/155965.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>程序员的共鸣 - 读《卓有成效的程序员》</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/15/155812.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Wed, 14 Sep 2011 23:36:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/15/155812.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/155812.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/15/155812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/155812.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/155812.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="color: #333333; font-family: 微软雅黑, verdana, Arial, sans-serif; background-color: #ffffff; "><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">最近读了《卓有成效的程序员》，感觉收获颇大。这是一本写给程序员的难得的好书。书中大都是一些浅显的道理，但作者将这些东西加以收集、归纳、总结，并最终成书。作者为了收集各种提高效率的工具和方法，东奔西走，可谓费了一番苦心。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">我觉得此书第一部分总结的一些法则非常好，我提取了一下：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">法则：&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h3><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">1.加速法则</h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 关注本质，而非形式</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 一个应用程序列表的有用程度与它的长度成反比&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">程序员的很多时间都浪费在找东西上</span>&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 华而不实的东西中看不中用</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 键盘输入总比导航快</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">首选键盘而非鼠标</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 地址栏是Windows资源管理器界面中最高效的部分</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">花点时间来学习你手边的所有隐藏的快捷键</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 环境切换会消耗时间</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">成批复制粘贴要比反复多次复制粘贴快</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 忘记历史就意味着你得再输入一遍</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 嵌入图形化工具的命令提示符让你鱼与熊掌兼得</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 在上下文中学习IDE快捷键，而不要去背长长的列表</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 当你第二次输入一个复杂结构时，将它做成模板</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 如果要对多行文本做同样的操作，就应该找出其中的模式，并把它记录为一个宏</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">不要总是重复输入相同的命令</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 每天花一点点时间来使每一天都更高效&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">2.专注法则</h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">精力越集中，思维越缜密</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 排除干扰：隔离策略，关掉不需要的提示，创造安静时间&nbsp;&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">草堆越大，从中找到一根针就越难</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 不要问文件树，要搜索</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 使用多显示器</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 虚拟桌面可以让原本杂乱无章的一大堆窗口变得整洁&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">3.自动化法则</h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 不要重新发明轮子</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 用Selenium浏览网页</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 不要浪费时间动手去做可以被自动化的事情</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 用Windows Power Shell替代批处理文件</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 驯服Subversion命令行</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 以创造性的方式解决问题，有助于在将来解决类似的问题</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">是否应该自动化的关键在于投资回报率和缓解风险</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 研究性的工作应该放在时间盒里做</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 别给牦牛剪毛&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">4.规范性法则<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;&nbsp;&nbsp; 对于任何你不自己去构建的东西，只在版本控制中保存一份副本<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 使用标准的构建服务器</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">通过复制粘贴来复用是邪恶的，不论你复制粘贴的是什么</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 利用虚拟平台使项目依赖标准化</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 不要让对象 - 关系映射工具（O/R映射器）违反规范原则&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 通过扩展。开放类（open class），或者部分类（partial class） 来为生成的代码增加行为<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 始终保持代码和数据结构的同步</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">过时的文档比没有文档更糟，因为它会主动误导你</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 任何需要费劲创造的东西，都让它的创造者欲罢不能</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">白板 + 数码相机强过任何CASE工具</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 尽量生成所有技术文档</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp;&nbsp;<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; line-height: 1.5; color: red; ">重复是软件开发中最大的阻力&nbsp;</span><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">工具：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h3><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">书中，还提到了大量的提高效率的工具，都是非常不错的。相信很多人都有自己的一个列表，下面是我电脑中必不可少的几款软件：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 1. FireFox 及其各类插件<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 2. Launchy启动加速器</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 3. Total Commander</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 4. ClipX多重剪切板</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 5. EmEditor文本编辑器&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 6. Vistual Studio的VA插件</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 7. Search And Replace</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 8. Everything</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 9. Miranda IM<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp; &nbsp; 10. ....&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">感触：&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h3><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">1. 愤怒的猴子&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">在书中的第二部分，提到了很多实践相关的内容。让我感触最深的是&#8220;愤怒的猴子&#8221;的故事：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&#8220;<em style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">早在20世纪60年代（那时候科学家们可以做任何疯狂的事情），行为科学家们进行了一项实验。他们把五只猴子和一架活梯放在一间屋子里，并在天花板上挂了一串香蕉。这些猴子很快就想到它们可以爬上梯子去吃香蕉，但每当它们靠近活梯的时候，科学家们就用冰水浸满整个屋子。我想你能猜到会发生什么：一群愤怒的猴子。很快，再没有一只猴子会去靠近那个梯子了。<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></em></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><em style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">之后，科学家们将其中一只猴子替换成另一只没有忍受过冰水折磨的新猴子。这只新猴子所做的第一件事就是直奔那架梯子，但当它这么做时其他所有猴子都痛打它。它不明白为什么，但很快就学乖了：不要去靠近那架梯子。科学家们逐渐将最初的那些猴子都替换成新猴子，直到这群猴子中谁都没有被水浸泡过，然而它们还是会去攻击任何靠近梯子的猴子。</em></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><em style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">这说明了什么？软件项目中许多惯例之所以存在，就因为&#8221;我们一直是那样做的&#8220;。换句话说，是因为愤怒的猴子。</em>&#8221;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">我们小组在制定C++相关的代码规范时就遇到过无数类似的问题。比如，在制定变量的命名规范时，我们针对是否采用匈牙利命名法争论了很久。有的人认为， 几乎以前看到的所有C++代码都采用了匈牙利命名法，甚至，微软定义的所有API都使用了此类命名法。刚开始，我也是有同样的疑惑。<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">后来，我们经过仔细分析C++匈牙利命名法由来，渐渐感觉我们就是那些愤怒的猴子，盲目跟从前人的方式，缺乏打破传统的勇气。C++有着其特殊的历史原因，很多标准一直沉淀下来并很少改变。我们再看看后来新生的那些编程语言，C#, Python&#8230;&#8230; 都抛弃了匈牙利命名法，同时再看看现在C++前沿的C++ 0x以及现在出版的一些书中，也渐渐放弃了对匈牙利命名法的使用。因为类型的意义在对象模型中越来越弱化。因此，最后我们放弃了匈牙利命名法这个老古董。&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">2. 敏捷开发<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">这本书带有强烈的ThoughtWorks色彩，敏捷的思想贯穿全书，包括测试驱动设计，白板，结对编程。这也让我对敏捷产生了更加强烈的兴趣。 其中有一段测试驱动开发TDD的一段故事：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&#8220;<em style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">记得第一次和一些已经习惯于单元测试的开发人员一起动手开始修改代码时，我也是非常紧张，因为大量的修改往往会破坏很多东西，但他们看起来丝毫没有犹豫。逐渐地，我也放下心来，因为我慢慢地认识到：有了测试的保证，完全可以放心大胆地去修改代码。</em>&#8221;&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h4 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">3. 有趣的故事&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></h4><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">书中还有一些有趣的故事，比如作者的一个朋友在和别人结对编程时，为了养成同伴使用快捷键的习惯，每当同伴未使用快捷键时，他都会要求将操作撤销，然后要求使用快捷键再重复操作3次。然后，在其凶狠的眼神中，同伴很快掌握了快捷键。&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><h3 style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; ">总结：</h3><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">这本书很薄，蕴藏的道理却不少，相信每个读过它的人都会从中收获。读过之后，我们不应该局限于书中提到的某些小技巧， 或是书中某一个细节，毕竟，提供效率的方法有很多很多，法则也有很多很多，一本书很难将其穷举完。我们应该从书中吸取其思想，并在实际工作和学习中不断总结，做一个真正的&#8220;卓有成效的程序员&#8221;！</p></span><img src ="http://www.cppblog.com/lauer3912/aggbug/155812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-15 07:36 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/15/155812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google Test 架构</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/15/155807.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Wed, 14 Sep 2011 22:40:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/15/155807.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/155807.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/15/155807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/155807.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/155807.html</trackback:ping><description><![CDATA[网址：<a href="http://code.google.com/p/googletest/">http://code.google.com/p/googletest/<br /><br />引文</a>：<a href="http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html">http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html<br /><span class="Apple-style-span" style="color: #333333; font-family: 微软雅黑, verdana, Arial, sans-serif; font-size: 13px; line-height: 24px; -webkit-text-decorations-in-effect: none; background-color: #ffffff; "><h1 class="postTitle" style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-weight: bold; color: #000000; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: #dddddd; font-size: 14px; "><a id="ctl03_TitleUrl" class="postTitle2" href="http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #399ab2; ">玩转Google开源C++单元测试框架Google Test系列(gtest)(总)</a></h1><div class="clear" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; clear: both; "></div><div class="postBody" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 14px; line-height: 1.5; "><div id="cnblogs_post_body" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">前段时间学习和了解了下Google的开源C++单元测试框架Google Test，简称gtest，非常的不错。 我们原来使用的是自己实现的一套单元测试框架，在使用过程中，发现越来越多使用不便之处，而这样不便之处，gtest恰恰很好的解决了。<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">其实gtest本身的实现并不复杂，我们完全可以模仿gtest，不断的完善我们的测试框架， 但最后我们还是决定使用gtest取代掉原来的自己的测试框架，原因是：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">1.不断完善我们的测试框架之后就会发觉相当于把gtest重新做了一遍，虽然轮子造的很爽，但是不是必要的。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">2.使用gtest可以免去维护测试框架的麻烦，让我们有更多精力投入到案例设计上。<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">3.gtest提高了非常完善的功能，并且简单易用，极大的提高了编写测试案例的效率。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">gtest的官方网站是：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://code.google.com/p/googletest/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">http://code.google.com/p/googletest/</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">从官方的使用文档里，你几乎可以获得你想要的所有东西&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://code.google.com/p/googletest/wiki/GoogleTestPrimer" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">http://code.google.com/p/googletest/wiki/GoogleTestPrimer</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><a target="_blank" href="http://code.google.com/p/googletest/wiki/GoogleTestPrimer" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; "></a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide</a>&nbsp;</p><a target="_blank" href="http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; "></a><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">如果还想对gtest内部探个究竟，就把它的代码下载下来研究吧，这就是开源的好处，哈！&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">官方已经有如此完备的文档了，为什么我还要写呢？一方面是自己记记笔记，好记性不如烂笔头，以后自己想查查一些用法也可以直接在这里查到，一方面是对于不想去看一大堆英文文档的朋友，在我这里可以快速的找到gtest相关的内容。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">下面是该系列的目录：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/03/31/1426758.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">1.玩转Google开源C++单元测试框架Google Test系列(gtest)之一 - 初识gtest</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">2.玩转Google开源C++单元测试框架Google Test系列(gtest)之二 - 断言</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/06/1430396.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">3.玩转Google开源C++单元测试框架Google Test系列(gtest)之三 - 事件机制</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/08/1431297.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">4.玩转Google开源C++单元测试框架Google Test系列(gtest)之四 - 参数化</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/08/1432043.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">5.玩转Google开源C++单元测试框架Google Test系列(gtest)之五 - 死亡测试</a>&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/10/1432789.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">6.玩转Google开源C++单元测试框架Google Test系列(gtest)之六 - 运行参数</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/11/1433744.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">7.玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/04/12/1434155.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">8.玩转Google开源C++单元测试框架Google Test系列(gtest)之八 - 打造自己的单元测试框架</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">额外篇：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2009/08/02/1536901.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">1.gtest中如何跳出当前测试案例</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" href="http://www.cnblogs.com/coderzh/archive/2010/01/09/beautiful-testcase.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">2.编写优美的GTest测试案例</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a target="_blank" id="homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl" href="http://www.cnblogs.com/coderzh/archive/2010/03/19/gtest_demo.html" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">3.gtest 参数化测试代码示例</a>&nbsp;(内含完整工程示例)</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></p></div><div id="MySignature" style="margin-top: 10px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><div id="MySignature" style="margin-top: 10px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><p id="LyjSignature" style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 60px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: dashed; border-right-style: dashed; border-bottom-style: dashed; border-left-style: dashed; border-top-color: #e0e0e0; border-right-color: #e0e0e0; border-bottom-color: #e0e0e0; border-left-color: #e0e0e0; background-color: #fffeee; background-image: url(http://www.cnblogs.com/images/cnblogs_com/lyj/o_info.png); background-attachment: scroll; font-family: 微软雅黑; background-position: 1% 50%; background-repeat: no-repeat no-repeat; ">作者：<a target="_blank" href="http://coderzh.cnblogs.com/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">CoderZh</a>（<a target="_blank" href="http://coderzh.cnblogs.com/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">CoderZh的技术博客 - 博客园</a>）<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />微博：<a target="_blank" href="http://t.sina.com.cn/coderzh" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">http://t.sina.com.cn/coderzh</a>&nbsp;<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />出处：<a target="_blank" href="http://coderzh.cnblogs.com/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #0066aa; border-bottom-width: 0px; border-bottom-style: initial; border-bottom-color: initial; ">http://coderzh.cnblogs.com</a><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />文章版权归本人所有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</p></div></div></div></span><br /></a><img src ="http://www.cppblog.com/lauer3912/aggbug/155807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-15 06:40 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/15/155807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>谈谈单元测试</title><link>http://www.cppblog.com/lauer3912/archive/2011/09/15/155806.html</link><dc:creator>RTY</dc:creator><author>RTY</author><pubDate>Wed, 14 Sep 2011 22:37:00 GMT</pubDate><guid>http://www.cppblog.com/lauer3912/archive/2011/09/15/155806.html</guid><wfw:comment>http://www.cppblog.com/lauer3912/comments/155806.html</wfw:comment><comments>http://www.cppblog.com/lauer3912/archive/2011/09/15/155806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lauer3912/comments/commentRss/155806.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lauer3912/services/trackbacks/155806.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="color: #333333; font-family: Verdana, Tahoma, 'BitStream vera Sans', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 17px; background-color: #ffffff; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">刚接触单元测试时，我实在是搞不懂这种测试到底有多大的意义，无非都是一些简单的ASSERT，但近年积累一些经验教训之后我才发现，单元测试这玩意儿真的是一种保证程序质量的强有力手段。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><span id="more-323" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">为什么这样说？举个最典型的例子，无论是开发新功能还是维护老程序，都不可避免的要反复修改某些代码，那该怎么保证修改的代码不会引入新的问题？如果你说你用人品担保，那我服了。我们应该需要一种可靠的手段来保证修改一个BUG不会引入两个三个BUG，或者不会让之前正确的功能出错，甚至是不会引入之前已经修改过的其它BUG。测试无疑是一种很好的手段，在没掌握其它更好的方法之前，很多人喜欢用人工测试，即编译 &#8211; 运行 &#8211; 输入典型值 &#8211; 看程序运行结果 &#8211; 如果出错 &#8211; 修改后再编译&#8230;&#8230;从长远来看，这种测试方法的缺点很明显：1、耗时耗力，每次修改代码后都需要人工重复测试所有的典型情况；2、容易出错、漏测，人脑太复杂，你很难记得几个月前的那个BUG到底是什么情况，因此没法测试，久而久之，N久前的那个BUG可能又神不知鬼不觉的重现了。相比之下，单元测试的优点就凸显出来了，把需要测试的典型情况编写为测试代码，然后编译运行即可完成自动化的测试，当发现BUG后，把它添加到测试用例，不仅可以提高测试覆盖率，还能保证以后不会再次引入同样的BUG，有了足够的单元测试（覆盖率），你就可以理直气壮的说代码没问题！当然引入单元测试会在前期花费不少的时间来编写测试代码，但相应的也会大大减少后期的维护工作，最主要的是能可靠的提高程序的质量，所以是值得的，甚至是必要的。（如果你编译过开源的Google Chromium浏览器，你会发现测试代码就占了不少，光是编译测试代码就得花很长的时间）</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">除了上面说的优点外，单元测试还有一些其它的好处，比如帮你理清设计。一些人反对单元测试就是因为说我们的应用太复杂了，没法做单元测试。其实不一定是应用复杂，而有可能是设计得有问题，导致了没有可测试性。比如有些人喜欢在CXXXDialog里编写所有的功能实现，要测试这样的代码，必须得创建出Dialog，可能还需要点击，这显然没法做单元测试，但如果把Dialog和业务逻辑分开设计，那至少业务逻辑是可测试的（暂不讨论UI的测试）。因此要做单元测试，就得设计好各个接口，保证某个接口只完成单一的功能，没有过多的耦合依赖。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">前面只是泛泛而谈了一些单元测试的皮毛，鼓吹了一些优点，有兴趣的自己找更详细的资料看吧。另推荐一个Google的开源C++测试框架<a href="http://code.google.com/p/googletest/" target="_blank" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #3b5998; ">googletest</a>。</p></span><img src ="http://www.cppblog.com/lauer3912/aggbug/155806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lauer3912/" target="_blank">RTY</a> 2011-09-15 06:37 <a href="http://www.cppblog.com/lauer3912/archive/2011/09/15/155806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>