﻿<?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++博客-C++ Programmer's Cookbook-随笔分类-VS2005/2008</title><link>http://www.cppblog.com/mzty/category/1588.html</link><description>&lt;br/&gt;  
&lt;br/&gt;
&lt;a href = "http://www.cppblog.com/mzty/archive/2007/03/02/19109.html"&gt;&lt;font size = 5 color ="#00FFFF"&gt;{C++ 基础}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/08/13/29922.html"&gt;&lt;font size = 5 color ="#00FFFF"&gt;{C++ 高级}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/04/16/22064.html"&gt;&lt;font size = 5 color ="#00FFFF"&gt;{C#界面，C++核心算法}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "http://www.cppblog.com/mzty/archive/2007/03/04/19163.html"&gt;&lt;font size = 5 color ="#00FFFF"&gt;{设计模式}&lt;font/&gt;&lt;/a&gt;

&lt;a href = "
http://www.cppblog.com/mzty/archive/2007/03/04/19167.html"&gt;&lt;font size = 5 color ="#FF0000"&gt;{C#基础}&lt;font/&gt;&lt;/a&gt;





</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 17:09:08 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 17:09:08 GMT</pubDate><ttl>60</ttl><item><title>Native c++ 和Managed 的 interop</title><link>http://www.cppblog.com/mzty/archive/2006/08/17/11354.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 17 Aug 2006 08:26:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/08/17/11354.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/11354.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/08/17/11354.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/11354.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/11354.html</trackback:ping><description><![CDATA[
		<p>4种方法:<br /><br />There are four main ways to do interop in .NET between the managed and native worlds. COM interop can be accomplished using Runtime Callable Wrappers (RCW) and COM Callable Wrappers (CCW). The common language runtime (CLR) is responsible for type marshaling (except in the rare scenarios where a custom marshaler is used) and the cost of these calls can be expensive. You need to be careful that the interfaces are not too chatty; otherwise a large performance penalty could result. You also need to ensure that the wrappers are kept up to date with the underlying component. That said, COM interop is very useful for simple interop scenarios where you are attempting to bring in a large amount of native COM code.</p>
		<p>The second option for interop is to use P/Invoke. This is accomplished using the DllImport attribute, specifying the attribute on the method declaration for the function you want to import. Marshaling is handled according to how it has been specified in the declaration. However, DllImport is only useful if you have code that exposes the required functions through a DLL export.</p>
		<p>When you need to call managed code from native code, CLR hosting is an option. In such a scenario, the native application has to drive all of the execution: setting up the host, binding to the runtime, starting the host, retrieving the appropriate AppDomain, setting up the invocation context, locating the desired assembly and class, and invoking the operation on the desired class. This is definitely one of the most robust solutions in terms of control over what and when things happen, but it is also incredibly tedious and requires a lot of custom code.</p>
		<p>The fourth option, and quite possibly the easiest and the most performant, is to use the interop capabilities in C++. By throwing the /clr switch, the compiler generates MSIL instead of native machine code. The only code that is generated as native machine code is code that just can't be compiled to MSIL, including functions with inline asm blocks and operations that use CPU-specific intrinsics such as Streaming SIMD Extensions (SSE). The /clr switch is how the Quake II port to .NET was accomplished. The Vertigo software team spent a day porting the original C code for the game to code that successfully compiled as C++ and then threw the /clr switch. In no time they were up and running on the .NET Framework. Without adding any additional binaries and simply by including the appropriate header files, managed C++ and native C++ can call each other without any additional work on the part of the developer. The compiler handles the creation of the appropriate thunks to go back and forth between the two worlds.</p>
<img src ="http://www.cppblog.com/mzty/aggbug/11354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-08-17 16:26 <a href="http://www.cppblog.com/mzty/archive/2006/08/17/11354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual C++ 编译器选项</title><link>http://www.cppblog.com/mzty/archive/2006/08/17/11336.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 17 Aug 2006 04:16:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/08/17/11336.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/11336.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/08/17/11336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/11336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/11336.html</trackback:ping><description><![CDATA[
		<p class="label">
				<b>来自msdn:http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/vccore/html/_core_compiler_options_listed_by_category.asp<br /><br />优化</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.o1.2c_2f.o2.asp">/O1</a>
										</td>
										<td width="71%">创建小代码</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.o1.2c_2f.o2.asp">/O2</a>
										</td>
										<td width="71%">创建快速代码</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.oa.2c_2f.ow.asp">/Oa</a>
										</td>
										<td width="71%">假设没有别名</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.ob.asp">/Ob</a>
										</td>
										<td width="71%">控制内联展开</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.od.asp">/Od</a>
										</td>
										<td width="71%">禁用优化</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.og.asp">/Og</a>
										</td>
										<td width="71%">使用全局优化</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.oi.asp">/Oi</a>
										</td>
										<td width="71%">生成内部函数</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.op.asp">/Op</a>
										</td>
										<td width="71%">改善浮点数一致性</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.os.asp">/Os</a>
										</td>
										<td width="71%">代码大小优先</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.os.asp">/Ot</a>
										</td>
										<td width="71%">代码速度优先</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.oa.2c_2f.ow.asp">/Ow</a>
										</td>
										<td width="71%">假定在函数调用中使用别名</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.ox.asp">/Ox</a>
										</td>
										<td width="71%">使用最大优化 (/Ob2gity /Gs)</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.oy.asp">/Oy</a>
										</td>
										<td width="71%">省略框架指针</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>代码生成</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrfarchminimumcpuarchitecture.asp">/arch</a>
										</td>
										<td width="71%">使用 SSE 或 SSE2 指令生成代码</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefeecomcompilation.asp">/clr</a>
										</td>
										<td width="71%">启用 C++ 的托管扩展并产生在公共语言运行库上运行的输出文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.eh.asp">/EH</a>
										</td>
										<td width="71%">指定异常处理模型</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/G3</a>
										</td>
										<td width="71%">优化代码以优选 386 处理器。在 Visual C++ 5.0 中已经停用，编译器将忽略此选项</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/G4</a>
										</td>
										<td width="71%">优化代码以优选 486 处理器。在 Visual C++ 5.0 中已经停用，编译器将忽略此选项</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/G5</a>
										</td>
										<td width="71%">优化代码以优选 Pentium</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/G6</a>
										</td>
										<td width="71%">优化代码以优选 Pentium Pro、Pentium II 和 Pentium III 处理器</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/G7</a>
										</td>
										<td width="71%">针对 Pentium 4 或 Athlon 优化代码。</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.g.asp">/GB</a>
										</td>
										<td width="71%">与 /G6 等效；将 _M_IX86 的值设置为 600</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gd.2c_2f.gr.2c_2f.gz.asp">/Gd</a>
										</td>
										<td width="71%">使用 <b>__cdecl</b> 调用约定</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.ge.asp">/Ge</a>
										</td>
										<td width="71%">激活堆栈探测</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gf.asp">/GF</a>
												<br />
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gf.asp">/Gf</a>
										</td>
										<td width="71%">启用字符串池</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gh.asp">/Gh</a>
										</td>
										<td width="71%">调用挂钩函数 <b>_penter</b></td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefghenable__pexithookfunction.asp">/GH</a>
										</td>
										<td width="71%">调用挂钩函数 <b>_pexit</b></td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcgrfglwholeprogramoptimization.asp">/GL</a>
										</td>
										<td width="71%">启用全程序优化</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gm_minimal.asp">/Gm</a>
										</td>
										<td width="71%">启用最小重新生成</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gr_option.asp">/GR</a>
										</td>
										<td width="71%">启用运行时类型信息 (RTTI)</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gd.2c_2f.gr.2c_2f.gz.asp">/Gr</a>
										</td>
										<td width="71%">使用 <b>__fastcall</b> 调用约定</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gs.asp">/Gs</a>
										</td>
										<td width="71%">控制堆栈探测</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gt.asp">/GT</a>
										</td>
										<td width="71%">支持使用静态线程本地存储区分配的数据的纤程安全</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gx.asp">/GX</a>
										</td>
										<td width="71%">启用同步异常处理</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gy.asp">/Gy</a>
										</td>
										<td width="71%">启用函数级链接</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.gd.2c_2f.gr.2c_2f.gz.asp">/Gz</a>
										</td>
										<td width="71%">使用 <b>__stdcall</b> 调用约定</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MD</a>
										</td>
										<td width="71%">使用 MSVCRT.lib 创建多线程 DLL</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MDd</a>
										</td>
										<td width="71%">使用 MSVCRTD.lib 创建调试多线程 DLL</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/ML</a>
										</td>
										<td width="71%">使用 LIBC.lib 创建单线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MLd</a>
										</td>
										<td width="71%">使用 LIBCD.lib 创建调试单线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MT</a>
										</td>
										<td width="71%">使用 LIBCMT.lib 创建多线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MTd</a>
										</td>
										<td width="71%">使用 LIBCMTD.lib 创建调试多线程可执行文件</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>输出文件</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fa.asp">/FA</a>
												<br />
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fa.asp">/Fa</a>
										</td>
										<td width="71%">创建列表文件<br />设置列表文件名</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fd.asp">/Fd</a>
										</td>
										<td width="71%">重命名程序数据库文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fe.asp">/Fe</a>
										</td>
										<td width="71%">重命名可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fm.asp">/Fm</a>
										</td>
										<td width="71%">创建映射文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fo.asp">/Fo</a>
										</td>
										<td width="71%">创建对象文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fp.asp">/Fp</a>
										</td>
										<td width="71%">指定预编译头文件名</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fr.2c_2f.fr.asp">/FR</a>
												<br />
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fr.2c_2f.fr.asp">/FR</a>
										</td>
										<td width="71%">生成浏览器文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefFxMergeInjectedCode.asp">/Fx</a>
										</td>
										<td width="71%">将插入的代码与源文件合并</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>调试</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrfgsbuffersecurity.asp">/GS</a>
										</td>
										<td width="71%">缓冲区安全检查</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefgz(catchrelease-builderrorsindebugbuild).asp">/GZ</a>
										</td>
										<td width="71%">与 <a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefrtcruntimechecks.asp">/RTC1</a> 相同</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefrtcruntimechecks.asp">/RTC</a>
										</td>
										<td width="71%">启用运行时错误检查</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vchowwp64detect64bitportabilityproblems.asp">/Wp64</a>
										</td>
										<td width="71%">检测 64 位可移植性问题</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.yd.asp">/Yd</a>
										</td>
										<td width="71%">将完整的调试信息放在所有对象文件中</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefylinjectpchreferencefordebuglib.asp">/Yl</a>
										</td>
										<td width="71%">创建调试库时插入 PCH 引用</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.z7.2c_2f.zd.2c_2f.zi.asp">/Z7</a>
										</td>
										<td width="71%">生成与 C 7.0 兼容的调试信息</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.z7.2c_2f.zd.2c_2f.zi.asp">/Zd</a>
										</td>
										<td width="71%">生成行号</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.z7.2c_2f.zd.2c_2f.zi.asp">/Zi</a>
										</td>
										<td width="71%">生成完整的调试信息</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>预处理器</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrfaispecifymetadatadirectories.asp">/AI</a>
										</td>
										<td width="71%">指定在解析传递到 #using 指令的文件引用时搜索的目录</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.c_uc.asp">/C</a>
										</td>
										<td width="71%">在预处理期间保留注释</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.d.asp">/D</a>
										</td>
										<td width="71%">定义常数和宏</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.e.asp">/E</a>
										</td>
										<td width="71%">将预处理器输出复制到标准输出</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.ep.asp">/EP</a>
										</td>
										<td width="71%">将预处理器输出复制到标准输出</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.fi.asp">/Fl</a>
										</td>
										<td width="71%">预处理指定的包含文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrffunameforcedusingfile.asp">/FU</a>
										</td>
										<td width="71%">强制使用文件名，就像它已被传递到 #using 指令一样</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.i.asp">/I</a>
										</td>
										<td width="71%">在目录中搜索包含文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.p.asp">/P</a>
										</td>
										<td width="71%">将预处理器输出写入文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.u.2c_2f.u.asp">/U</a>
										</td>
										<td width="71%">移除预定义宏</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.u.2c_2f.u.asp">/u</a>
										</td>
										<td width="71%">移除所有的预定义宏</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.x.asp">/X</a>
										</td>
										<td width="71%">忽略标准包含目录</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a class="POPUP" href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.z7.2c_2f.zd.2c_2f.zi.asp">/ZI</a>
										</td>
										<td width="71%">将调试信息包含在与“编辑并继续”兼容的程序数据库中</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>语言</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vd.asp">/vd</a>
										</td>
										<td width="71%">取消或启用隐藏的 vtordisp 类成员</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vmb.2c_2f.vmg.asp">/vmb</a>
										</td>
										<td width="71%">对指向成员的指针使用最佳的基</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vmb.2c_2f.vmg.asp">/vmg</a>
										</td>
										<td width="71%">对指向成员的指针使用完全一般性</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vmm.2c_2f.vms.2c_2f.vmv.asp">/vmm</a>
										</td>
										<td width="71%">声明多重继承</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vmm.2c_2f.vms.2c_2f.vmv.asp">/vms</a>
										</td>
										<td width="71%">声明单一继承</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.vmm.2c_2f.vms.2c_2f.vmv.asp">/vmv</a>
										</td>
										<td width="71%">声明虚拟继承</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.za.2c_2f.ze.asp">/Za</a>
										</td>
										<td width="71%">禁用语言扩展</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefzcconformance.asp">/Zc</a>
										</td>
										<td width="71%">在 <a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.za.2c_2f.ze.asp">/Ze</a> 下指定标准行为</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.za.2c_2f.ze.asp">/Ze</a>
										</td>
										<td width="71%">启用语言扩展</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.zg.asp">/Zg</a>
										</td>
										<td width="71%">生成函数原型</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.zl.asp">/Zl</a>
										</td>
										<td width="71%">从 .obj 文件中移除默认库名</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.zp.asp">/Zp</a>
												<i>n</i>
										</td>
										<td width="71%">封装结构成员</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.zs.asp">/Zs</a>
										</td>
										<td width="71%">只检查语法</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>链接</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.f.asp">/F</a>
										</td>
										<td width="71%">设置堆栈大小</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/LD</a>
										</td>
										<td width="71%">创建动态链接库</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/LDd</a>
										</td>
										<td width="71%">创建调试动态链接库</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.link.asp">/link</a>
										</td>
										<td width="71%">将指定的选项传递给 LINK</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MD</a>
										</td>
										<td width="71%">使用 MSVCRT.lib 编译以创建多线程 DLL</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MDd</a>
										</td>
										<td width="71%">使用 MSVCRTD.lib 编译以创建调试多线程 DLL</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/ML</a>
										</td>
										<td width="71%">使用 LIBC.lib 编译以创建单线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MLd</a>
										</td>
										<td width="71%">使用 LIBCD.lib 编译以创建调试单线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MT</a>
										</td>
										<td width="71%">使用 LIBCMT.lib 编译以创建多线程可执行文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp">/MTd</a>
										</td>
										<td width="71%">使用 LIBCMTD.lib 编译以创建调试多线程可执行文件</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>预编译头</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrfyignoreprecompiledheaderoptions.asp">/Y-</a>
										</td>
										<td width="71%">忽略当前生成中的所有其他预编译头编译器选项</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.yc.asp">/Yc</a>
										</td>
										<td width="71%">创建预编译头文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.yd.asp">/Yd</a>
										</td>
										<td width="71%">将完整的调试信息放在所有对象文件中</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.yu.asp">/Yu</a>
										</td>
										<td width="71%">在生成期间使用预编译头文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.yx.asp">/YX</a>
										</td>
										<td width="71%">自动处理预编译头</td>
								</tr>
						</tbody>
				</table>
		</div>
		<p class="label">
				<b>杂项</b>
		</p>
		<div class="tablediv">
				<table class="dtTABLE" cellspacing="0" width="80%" border="1">
						<tbody>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vctbsspecifyresponsefile.asp">@</a>
										</td>
										<td width="71%">指定响应文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.help.asp">/?</a>
										</td>
										<td width="71%">列出编译器选项</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.c_lc.asp">/c</a>
										</td>
										<td width="71%">编译但不链接</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.h.asp">/H</a>
										</td>
										<td width="71%">限制外部（公共）名称的长度</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.help.asp">/HELP</a>
										</td>
										<td width="71%">列出编译器选项</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.j.asp">/J</a>
										</td>
										<td width="71%">更改默认的 <b>char</b> 类型</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vclrfnologosuppressdisplayofbanner.asp">/nologo</a>
										</td>
										<td width="71%">取消显示登录版权标志</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.qi0f.asp">/QI0f</a>
										</td>
										<td width="71%">确保 Pentium 0F 指令没有问题</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.qifdiv.asp">/QIfdiv</a>
										</td>
										<td width="71%">FDIV、FPREM、FPTAN 和 FPATAN 指令有缺陷的 Intel Pentium 微处理器的变通方法</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefqifistsuppress_ftol.asp">QIfist</a>
										</td>
										<td width="71%">当需要从浮点类型转换为整型时取消 Helper 函数 <b>_ftol</b> 的调用</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefshowincludes.asp">/showIncludes</a>
										</td>
										<td width="71%">在编译期间显示所有包含文件的列表</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.tc.2c_2f.tp.asp">/Tc</a>
												<br />
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.tc.2c_2f.tp.asp">/TC</a>
										</td>
										<td width="71%">指定 C 源文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.tc.2c_2f.tp.asp">/Tp</a>
												<br />
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.tc.2c_2f.tp.asp">/TP</a>
										</td>
										<td width="71%">指定 C++ 源文件</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.v.asp">/V</a>
										</td>
										<td width="71%">设置版本字符串</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.w.2c_2f.w.asp">/W</a>
										</td>
										<td width="71%">设置警告等级</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.w.2c_2f.w.asp">/w</a>
										</td>
										<td width="71%">禁用所有警告</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.w.2c_2f.w.asp">/Wall</a>
										</td>
										<td width="71%">启用所有警告，包括默认情况下禁用的警告</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/vcrefwlenableonelinediagnostics.asp">/WL</a>
										</td>
										<td width="71%">在从命令行编译 C++ 源代码时启用错误信息和警告消息的单行诊断</td>
								</tr>
								<tr valign="top">
										<td width="29%">
												<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_.2f.zm.asp">/Zm</a>
										</td>
										<td width="71%">指定预编译头内存分配限制</td>
								</tr>
						</tbody>
				</table>
		</div>
		<h4 class="dtH4">请参见</h4>
		<p>
				<a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_overviews.3a_.compiling_and_linking.asp">C/C++ 生成参考</a> | <a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_compiler_reference.asp">编译器选项</a> | <a href="http://msdn.microsoft.com/library/CHS/vccore/html/_core_set_compiler_options.asp">设置编译器选项</a></p>
<img src ="http://www.cppblog.com/mzty/aggbug/11336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-08-17 12:16 <a href="http://www.cppblog.com/mzty/archive/2006/08/17/11336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调试breakpoint高级</title><link>http://www.cppblog.com/mzty/archive/2006/08/16/11289.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 16 Aug 2006 06:47:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/08/16/11289.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/11289.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/08/16/11289.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/11289.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/11289.html</trackback:ping><description><![CDATA[breakpoint的右键菜单:<br><img style="WIDTH: 585px; HEIGHT: 264px" height=264 alt=o_tiaoshi2.jpg src="http://www.cppblog.com/images/cppblog_com/mzty/2021/o_tiaoshi2.jpg" width=585 border=0><br><br>
<div class=itemTitleStyle><font style="BACKGROUND-COLOR: #ff1493">Tracepoints</font></div>
<div class=itemBodyStyle>
<p>When you have a "mystery" bug to solve, tracepoints are a vital part of your debugging arsenal. Single stepping and looking through code can be S-L-O-O-O-O-W and if you don't even know what you're looking for, it can consume hours and hours of effort. Tracepoints really speed things up. They're like breakpoints that don't break. In a way, they go back to the old "printf debugging" -- but you don't need to make code changes and recompile to change them.</p>
<p>To set a tracepoint, first set a breakpoint, then right-click on the red dot that appears in the margin and choose When Hit:</p>
<p><img src="http://www.gregcons.com/KateBlog/content/binary/tracepoint1.gif" border=0></p>
<p>In the dialog that appears, click the Print A Message box and edit the starter message you are given. You can include any expression in braces and it will be evaluated when control reaches the tracepoint:</p>
<p><img src="http://www.gregcons.com/KateBlog/content/binary/tracepoint2.gif" border=0></p>
<p>Leave the Continue Execution box checked so that you don't break. Tracepoints are identified by red diamonds instead of red dots:</p>
<p><img src="http://www.gregcons.com/KateBlog/content/binary/tracepoint3.gif" border=0></p>
<p>The output from the tracepoints appears in the output window of your debug session:</p>
<p><img style="WIDTH: 554px; HEIGHT: 126px" height=126 src="http://www.gregcons.com/KateBlog/content/binary/tracepoint4.gif" width=554 border=0></p>
<p>You can set up something suspicious, let it run, then pore through the tracepoint output and see what you learn. It's a huge timesaver when you're tackling a "we don't even know where to start" bug. Plus, if the issue is related to threading or async issues in any way (and you know me, I keep preaching we will all be facing async issues eventually) then you don't have to worry that pausing execution suppresses the collisions. I recently helped a client solve a big hairy this-stuff-fails-for-our-biggest-customer-only bug using tracepoints... and a few other tricks I will cover in upcoming posts.</p>
<div class=itemTitleStyle><font style="BACKGROUND-COLOR: #ff1493">Conditional breakpoints</font></div>
<div class=itemBodyStyle>
<p>Conditional breakpoints were another really important tool in solving a recent "only happens at the big installations" bug in a big and complicated C++ application. We wanted to debug the code with as few rebuilds as possible and we really didn't know how parts of it worked at all. <a href="http://www.gregcons.com/KateBlog/ct.ashx?id=eb64dfe1-fde4-413e-be11-2445b3f7d5e1&amp;url=http%3a%2f%2fwww.gregcons.com%2fKateBlog%2fCommentView.aspx%3fguid%3dc5590e77-c53e-4a2a-a632-80e10fe611bb" ?=""><strong><font color=#004183>Tracepoints </font></strong></a>helped us to figure out a lot of it in a short time. We didn't have a decent repro case though, so here's what we did:</p>
<ul>
    <li>created a script to add an audit table and some triggers that write to it
    <li>created a script to remove those triggers and the table
    <li>created a batch file to run a server in verbose mode, and redirect the output to a text file (remembering DOS commands sure can be helpful...&nbsp;&nbsp; <strong>myapp.exe -verbose &gt;logfile.txt</strong> was the magic phrase.)
    <li>wrote some instructions for the support guy to grab a backup of the database, run the first script, run the batch file, let it run all night, then in the morning grab another backup of the database, run the second script, and stop the batch file.</li>
</ul>
<p>Now we ran some queries on the morning version of the database to confirm that at least one X was missing a Y that should have been calculated overnight. We even had the Xid. Thanks to the tracepoint work of the previous day we knew where to be suspicious. A little digging in the trigger output told us whether the problem was "didn't get added" or "got added, but then got deleted". The last step was conditional breakpoints. These let us say "only stop here when you're processing the X with this Xid." </p>
<p><img src="http://www.gregcons.com/KateBlog/content/binary/condbreakpoint.gif" border=0></p>
<p>This really saves time when you just need to drill into what's happening in the case that is going wrong. You get to it by right clicking the red dot or diamond and choosing Condition. </p>
<br>
<div class=itemTitleStyle><font style="BACKGROUND-COLOR: #ff1493">One more breakpoint tip - hit count</font></div>
<div class=itemBodyStyle>
<p><a href="http://www.gregcons.com/KateBlog/ct.ashx?id=d9e91a84-e206-4e03-b21f-b38fcf70b138&amp;url=http%3a%2f%2fwww.gregcons.com%2fKateBlog%2fCommentView.aspx%3fguid%3deb64dfe1-fde4-413e-be11-2445b3f7d5e1" ?=""><strong><font color=#005bba>Conditional breakpoints</font></strong></a> are cool when you know the value of one variable that is associated with trouble: this only blows up&nbsp;when Xid&nbsp;is 1234. They can also be used to reduce the boredom of single stepping. Say you've got some loop that goes around a few hundred times building up some string or array or something. You don't want to keep going round and round and round... it would be nice to jump ahead to halfway through, for example, and see how things are looking. Now if this is a for loop with a handy named variable, say</p>
<p>&#160;</p>
<pre>for (int i = 0; i&lt;1000; i++)</pre>
<p>&#160;</p>
<p>Then you can use a conditional breakpoint and say "stop when i is 200". Or you could be clever and stop when <strong>i % 200 </strong>is 0 -- so that's every 200 times. But what if there's no i? What if you're going through a file or a recordset/dataset/resultset and you're going until the end? You don't want to add some fake variable that gets incremented each time through the loop, just so you can set a breakpoint that breaks on certain values of that variable. Instead you want to use the hit count property of the breakpoint. Just right click the red dot and choose Hit Count. There you can set the breakpoint to break whenever it's hit, just the 10th time it's hit, every tenth time (10, 20, 30 etc) or every time after the 10th time Or, of course, whatever number you want instead of 10:</p>
<p><img src="http://www.gregcons.com/KateBlog/content/binary/hitcount.gif" border=0></p>
<p>Don't debug the slow way when there are tools to make you so much faster!<br><br><font style="BACKGROUND-COLOR: #ff1493">Filter</font>&nbsp;&nbsp; 下次再介绍:<br><br><img height=336 alt=o_tiaoshi.jpg src="http://www.cppblog.com/images/cppblog_com/mzty/2021/o_tiaoshi.jpg" width=406 border=0><br><br><br><font style="BACKGROUND-COLOR: #ee82ee">注意:c#的也可以用的啊....<br><br><br><br>来自:http://www.gregcons.com/KateBlog/CategoryView.aspx?category=C%2B%2B<br></font></p>
</div>
</div>
</div><img src ="http://www.cppblog.com/mzty/aggbug/11289.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-08-16 14:47 <a href="http://www.cppblog.com/mzty/archive/2006/08/16/11289.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TestRunner</title><link>http://www.cppblog.com/mzty/archive/2006/07/29/10675.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Sat, 29 Jul 2006 05:31:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/07/29/10675.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/10675.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/07/29/10675.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/10675.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/10675.html</trackback:ping><description><![CDATA[
		<h2>testrunner</h2>
		<p>
				<a href="http://morningspace.51.net/resource/cppunit/textui.html">
				</a> </p>
		<h2>
				<a href="http://www.mailframe.net/Products/TestRunner/default.aspx">http://www.mailframe.net/Products/TestRunner/default.aspx</a>
		</h2>
		<h2>TestRunner Provides </h2>
		<ul>
				<li>Test Driven Development inside Visual Studio 2005 
</li>
				<li>Integrated debugging from a simple context menu in the editor 
</li>
				<li>File, method, and line level code coverage in the editor 
</li>
				<li>Graphical test feedback directly in the Visual Studio editor 
</li>
				<li>Console &amp; Trace redirection to the Output Window 
</li>
				<li>Non-blocking test runs -- program while you test on a background thread 
</li>
				<li>Test failure tool tips and line markers 
</li>
				<li>Ultra Performance tested with suites of 1400 unit tests </li>
		</ul>
		<p> </p>
		<ul>
				<li>TestRunner will change the way you NUnit test by making it a seamless experience with programming. Tests run in the background and richly interact with the Visual Studio editor instead of a separate program, saving you from the window shuffle or losing your place in your code. <span class="hot">Unit testing</span>, <span class="hot">code coverage</span>, and now <span class="hot">performance profiling</span> all in one convenient tool. </li>
		</ul>
		<p>cppunit:   <a href="http://morningspace.51.net/resource/cppunit/textui.html">http://morningspace.51.net/resource/cppunit/textui.html</a><br /> </p>
		<p>------------------------------------------------------------------------------------------------------------------------------------<br /></p>
		<div class="postText">TestDriven.NET网址：<a href="http://www.testdriven.net/">http://www.testdriven.net/</a><br />下载地址：<a href="http://www.testdriven.net/Default.aspx?tabid=27">http://www.testdriven.net/Default.aspx?tabid=27</a><br />博客园下载地址：<a href="http://downloads.cnblogs.com/TestDriven.NET-1.0.915d.zip">http://downloads.cnblogs.com/TestDriven.NET-1.0.915d.zip</a><br />使用帮助：<a href="http://www.testdriven.net/Default.aspx?tabid=29">http://www.testdriven.net/Default.aspx?tabid=29</a><br /><br />使用感受： <br />1、与VS.NET集成得很不错, 使用起来很方便, 比如我们运行一个测试方法，直接在这个方法上点击右键Run Test(s): <br /><img height="250" hspace="5" src="http://www.cnblogs.com/images/cnblogs_com/dudu/testdivern001.gif" width="483" align="baseline" /><br />然后在VS.NET的输出窗口中输出测试结果。Cool! 错误信息会显示在任务窗口。 <br />2、在“解决方案资源管理器”中，可以选中相应的项目点击右键运行测试，可以通过Test With NUnit GUI启动NUnit GUI运行测试。 <br />3、通过Tests With Debugger, 在Debug模式中运行测试， <br />4、不需要另外安装NUnit。TestDriven.NET已经自带NUnit。<br /><br />------------------------------------------------------------------<br /><br />nunit的使用:<br /><br /><a href="http://ltp.cnblogs.com/archive/2005/12/03/289720.html">http://ltp.cnblogs.com/archive/2005/12/03/289720.html</a></div>
<img src ="http://www.cppblog.com/mzty/aggbug/10675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-07-29 13:31 <a href="http://www.cppblog.com/mzty/archive/2006/07/29/10675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>升级VC7项目到VC8的注意事项(转)</title><link>http://www.cppblog.com/mzty/archive/2006/07/24/10386.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Mon, 24 Jul 2006 00:47:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/07/24/10386.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/10386.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/07/24/10386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/10386.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/10386.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 升级VC7项目到VC8的注意事项																																																																																																																																																																																...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2006/07/24/10386.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/10386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-07-24 08:47 <a href="http://www.cppblog.com/mzty/archive/2006/07/24/10386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用API实现1/1000秒的性能测试类</title><link>http://www.cppblog.com/mzty/archive/2006/06/16/8636.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 16 Jun 2006 06:07:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/06/16/8636.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/8636.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/06/16/8636.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/8636.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/8636.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: //				 MbUnit Test Framework				//				 				//				 Copyright (c) 2004 Jonathan de Halleux				//																								//				 This software is provided 'as-is', without any expr...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2006/06/16/8636.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/8636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-06-16 14:07 <a href="http://www.cppblog.com/mzty/archive/2006/06/16/8636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual Studio 2005 Team System：构建健壮而可靠的软件</title><link>http://www.cppblog.com/mzty/archive/2006/06/16/8630.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 16 Jun 2006 04:16:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/06/16/8630.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/8630.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/06/16/8630.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/8630.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/8630.html</trackback:ping><description><![CDATA[
		<h1>Visual Studio 2005 Team System：构建健壮而可靠的软件</h1>
		<h2 class="subtitle">
		</h2>
		<div class="date">发布日期： 6/21/2005<span class="datePipe"> | </span>更新日期： 6/21/2005</div>
		<div class="overview">
				<p>Kamran Iqbal<br />Microsoft Corporation</p>
				<p>适用于：</p>
				<p>Microsoft Visual Studio® 2005 Team System</p>
				<p>
						<b>摘要：</b>描述 Visual Studio 2005 Team System 提供的代码分析和性能工具。</p>
				<p>
						<b>注</b> 本文档于产品投入生产之前编写，因此您可能会发现这里所包含的细节与发布的产品有不一致的地方。文中的信息均依据撰写本文时的产品状况，仅供您在规划时参考。如有更改，恕不另行通知。Microsoft 拥有本文档中的主题所涉及的专利、专利应用程序、商标、版权或其他的知识产权。除非 Microsoft 以任何书面许可协议明确提供，向您提供本文档并没给予您使用这些专利、商标、版权或其他知识产权的任何许可证。</p>
		</div>
		<center>
				<img title="" height="6" alt="*" src="http://img.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif" width="30" border="0" />
		</center>
		<div style="HEIGHT: 18px">
		</div>
		<h5 style="PADDING-TOP: 2px">本页内容</h5>
		<table style="MARGIN-TOP: 7px; MARGIN-BOTTOM: 12px" cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#EDC">
												<img height="9" alt="简介" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#EDC">简介</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#EGC">
												<img height="9" alt="分析工具支持" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#EGC">分析工具支持</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#ETC">
												<img height="9" alt="我们的解决方案" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#ETC">我们的解决方案</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#E5C">
												<img height="9" alt="Visual Studio 中的工具集成" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#E5C">Visual Studio 中的工具集成</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#E1GAC">
												<img height="9" alt="小结" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#E1GAC">小结</a>
								</td>
						</tr>
				</tbody>
		</table>
		<a name="EDC">
		</a>
		<h2>简介</h2>
		<p>要开发健壮而可靠的软件，开发人员需要一套集成分析工具，来帮助他们在开发的早期检测代码缺陷和性能问题。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">返回页首</a>
		</div>
		<a name="EGC">
		</a>
		<h2>分析工具支持</h2>
		<p>过去，由于 Visual Studio 中缺少对代码分析的支持，因此开发人员不得不购买第三方工具，构建自定义分析工具，或者发布未经分析的代码。 </p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>花费额外的成本购买第三方工具。 </p>
										<p>从众多的分析工具中选择一个既能满足软件分析的要求又在预算限制范围之内的工具，未必总是一项轻松的任务。另外，这些工具可能没有集成到 Visual Studio 集成开发环境 (IDE) 中，因此通常需要花费额外的时间来学习如何顺利地使用它们。 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>构建自定义分析工具。 </p>
										<p>构建自定义分析工具需要资源、技能和经验。这对大多数公司中的开发团队而言是不现实的，仅仅是少数公司可以担负得起的选择。 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>发布未经分析的代码。 </p>
										<p>在工时期限和预算限制紧张的情况下，发布未经分析的代码似乎是一种正确的方法，但如果软件在部署之后发生故障，可能证明采用这种错误方法的代价不菲。 </p>
								</td>
						</tr>
				</tbody>
		</table>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">返回页首</a>
		</div>
		<a name="ETC">
		</a>
		<h2>我们的解决方案</h2>
		<p>在 Visual Studio 2005 Team System 中，开发人员将会看到一套全新的、完全集成到 IDE 中的分析工具。这种分析工具与开发环境的紧密集成，可以帮助开发人员在产品开发的早期检测并修复代码缺陷和性能问题。这还可以帮助团队有效且高效地管理软件开发生命周期（Software Development Life Cycle，SDLC）。</p>
		<p>在 Visual Studio 2005 Team System 中，有两类分析工具可用于构建健壮而可靠的软件： </p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>代码分析工具 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>性能工具 </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>在开发环境中集成分析工具可以帮助开发人员检测与编码、性能及安全性相关的问题。此外，可将代码分析工具作为签入策略的一部分用于每日构建 (nightly build) 过程，使开发团队能够在将代码签入到源树 (source tree) 之前修正缺陷。通过在开发的早期（而不是后期）更正问题，团队可降低修复代码缺陷的总体成本。</p>
		<p>除了完全集成到 IDE 中之外，开发人员还可以从命令行使用这些工具。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/dnvsentvstsdev.mspx#top">返回页首</a>
		</div>
		<a name="E5C">
		</a>
		<h2>Visual Studio 中的工具集成</h2>
		<p>在 Visual Studio 2005 Team System 中，通过使用代码分析工具和性能工具，开发人员可以对代码进行静态和动态分析。</p>
		<p>代码分析工具</p>
		<p>代码分析工具的目标是使开发人员能够对其项目进行静态分析，以检测和修复代码缺陷。为了实现这个目标，Visual Studio 2005 Team System 中包含了两个工具： </p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>PRE<i>f</i>ast </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>FxCop </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>PRE<i>f</i>ast</p>
		<p>PRE<i>f</i>ast 是一个静态分析工具，它为开发人员提供有关其 C/C++ 源代码中可能存在缺陷的信息。PRE<i>f</i>ast 报告的常见代码错误包括缓冲区溢出、未初始化内存、空指针取消引用、内存泄漏和资源短缺。</p>
		<p>
				<em>IDE </em>
				<em>集成</em>
		</p>
		<p>为了使开发人员能够自然地使用分析工具，可以将 PRE<i>f</i>ast 完全集成到 IDE 中。通过在项目的 <b>Property Pages</b> 上选择 <b>Yes (/prefast)</b>，开发人员可以轻松启用 PRE<i>f</i>ast，如图 1 所示。</p>
		<div style="WIDTH: 470px">
				<img height="317" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig01.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 1. </b>
						<b>启用</b>
						<b> PRE</b>
						<b>
								<i>f</i>
						</b>
						<b>ast</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>在生成过程中，为源代码生成的任何 PRE<i>f</i>ast 警告都出现在 <b>Error List</b> 中。这些警告包括缺陷路径信息（如果有）；双击突出显示缺陷路径的警告，可以进入代码编辑器中的警告，如图 2 所示。</p>
		<div style="WIDTH: 470px">
				<img height="226" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig02.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 2. PRE</b>
						<b>
								<i>f</i>
						</b>
						<b>ast </b>
						<b>警告</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<i>#pragma support</i>
		</p>
		<pre class="codeSample">Developers can use the #pragma directive to treat warnings as errors, or disable warnings, as shown below.
#pragma warning (error: 6260)  //treat warning 6260 as an error
#pragma warning (disable: 6011)  //disable warning 6011
</pre>
		<p>
				<em>批注支持</em>
		</p>
		<p>PRE<i>f</i>ast 还支持批注以改善代码分析的精确性。批注提供有关函数参数和返回类型的之前和之后条件的附加信息。</p>
		<pre class="codeSample">#include 
[SA_Post( MustCheck=SA_Yes )] double* CalcSquareRoot
( 
   [SA_Pre( Null=SA_No )] double* source, 
   unsigned int size
)
</pre>
		<p>在上面的示例中： </p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>[SA_Post ( MustCheck=SA_Yes)] 要求调用方检查 CalcSquareRoot 的返回值 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>[SA_Pre ( Null=SA_No)] 要求调用方将非空参数“source”传递给 CalcSquareRoot </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<em>命令行支持</em>
		</p>
		<p>除了与开发环境完全集成之外，开发人员还可以从命令行使用 PRE<i>f</i>ast，如下所示。</p>
		<pre class="codeSample">C:\&gt;cl /prefast Sample.cpp
</pre>
		<p>FxCop</p>
		<p>FxCop 是一个静态分析工具，它分析托管代码程序集并报告有关程序集的信息，例如，与<a href="http://msdn.microsoft.com/library/en-us/cpgenref/html/cpconNETFrameworkDesignGuidelines.asp" target="_blank"> Microsoft .NET Framework Design Guidelines</a> 中阐述的编程和设计规则相冲突。FxCop 表示在分析过程中作为规则执行的检查。规则是一段托管代码，该代码分析程序集并返回有关它发现结果的消息。规则消息识别任何相关的编程和设计问题，并在可能的情况下，提供有关如何修复目标的信息。</p>
		<p>
				<em>IDE </em>
				<em>集成</em>
		</p>
		<p>为了使开发人员能够自然地使用分析工具，开发人员可以在项目的 <b>Property Pages</b> 上选择 <b>Run FxCop</b>，如图 3 所示。</p>
		<div style="WIDTH: 470px">
				<img height="335" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig03.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 3. </b>
						<b>启用</b>
						<b> FxCop</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>有关包含或排除规则，将规则作为警告或错误的附加选项，也可以在 <b>Property Pages</b> 中找到，如图 4 所示。</p>
		<div style="WIDTH: 470px">
				<img height="128" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig04.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 4. FxCop </b>
						<b>规则</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>一旦启用 FxCop，在生成过程中，FxCop 就会在 <b>Error List</b> 中报告冲突，如图 5 所示。</p>
		<div style="WIDTH: 470px">
				<img height="183" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig05.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 5. FxCop </b>
						<b>规则冲突</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<b>Error List</b> 提供有关规则冲突的信息和建议，以便于您纠正错误。只需在 <b>Error List</b> 中双击规则冲突，即可轻松地定位到触犯了规则的代码行。</p>
		<p>
				<em>MSBuild </em>
				<em>集成</em>
		</p>
		<p>Visual Studio 的下一个版本从根本上改进了生成过程，其方法是引入一个新的、名为 MSBuild 的生成引擎。可以通过 MSBuild 系统调用 FxCop。这使开发人员能够从命令行运行托管项目上的 FxCop。</p>
		<p>性能工具</p>
		<p>在 Visual Studio 2005 Team System 中，开发人员可以通过性能工具来度量、计算和定位代码中与性能相关的问题。这些工具都完全集成到 IDE 中，以提供无缝、友好的用户体验。</p>
		<p>性能工具支持两种分析方法： </p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>采样 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>使用仪器 </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>在采样的过程中，数据收集基础结构将定期中断正在执行的应用程序，以确定正在执行的是哪个函数，并增加函数的采样计数。它存储有关准备函数调用的调用堆栈的信息。</p>
		<p>应用程序退出后，收集到的所有数据会生成为一个报告文件，您可以使用 IDE 中集成的报告功能轻松地查看该文件。</p>
		<p>采样的优势在于低开销，因为这只是定期中断应用程序。这使得应用程序的行为能够更接近实际情况。这种方法的缺点是，它只能获取已采样函数的相关性能数据。有可能没有对需要采样的函数进行采样，因而无法获取有关该函数的信息。 </p>
		<p>使用仪器的优势在于可以收集应用程序的特定部分的精确性能数据。在使用仪器的过程中，“enter”和“exit”探针被插入到应用程序的函数中。这些探针将报告返回给数据收集基础结构，并允许用户捕获函数执行所需的精确时间（或其他衡量标准）。</p>
		<p>分析应用程序</p>
		<p>分析应用程序的首选使用模式是首先开始采样，然后根据采样所产生的结果检测应用程序的特定方面。</p>
		<p>分析应用程序的过程相当简单。首先创建一个新的性能会话。在 Visual Studio 2005 Team System 中，可以使用 <b>Performance Session Wizard</b> 创建一个新的性能会话。</p>
		<p>Performance Session Wizard</p>
		<p>
				<b>Performance Session Wizard</b> 设置分析应用程序的必要环境。在 Visual Studio 2005 Team System 中，该向导为 EXE、DLL 和 ASP.NET 应用程序提供内置支持。</p>
		<p>可以使用该向导创建一个 <b>New Performance Session</b>，如图 6 所示。</p>
		<div style="WIDTH: 447px">
				<img height="448" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig06.gif" width="447" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 6. </b>
						<b>启动性能向导</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<b>注</b> 要手动创建一个新的性能会话，请使用菜单上的 <b>New Performance Session</b> 命令。可以采用这种方法来手动分析其他类型的应用程序（例如，Windows 服务）。</p>
		<p>Performance Explorer</p>
		<p>性能会话作为运行会话向导或手动创建会话的结果而创建。<b>Performance Explorer</b> 可以将其直观地表示出来，如图 7 所示。</p>
		<div style="WIDTH: 182px">
				<img height="144" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig07.gif" width="182" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 7. </b>
						<b>性能资源管理器</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<b>Performance Explorer</b> 给用户呈现了层次结构。该层次结构的根节点表示 <b>Performance Session</b>。这种节点的属性是用户在创建 <b>Performance Session</b> 时设置的属性。如果用户使用 <b>Performance Session Wizard</b> 创建会话，则这些属性体现了用户在使用向导的过程中所选择的值。如果用户手动创建 <b>Performance Session</b>，则这些属性包含了它们的默认值。</p>
		<p>根节点有两个子节点：<b>Targets</b> 节点和 <b>Reports</b> 节点。<b>Targets</b> 节点包含一个或多个目标，目标可以是 EXE、DLL 或 ASP.NET 应用程序。</p>
		<p>
				<b>Reports</b> 节点包含与某个特定 <b>Performance Session</b> 相关的所有报告。</p>
		<p>性能会话报告</p>
		<p>一旦应用程序执行完毕，系统就会将一个性能会话报告自动添加到 <b>Reports</b> 节点。可以通过下面的视图来查看这些报告：</p>
		<p>
				<em>Summary </em>
				<em>视图</em>
		</p>
		<p>Summary 视图为开发人员提供了其调查的起点。它显示应用程序执行过程中开销最高的函数，如图 8 所示。从该视图中的每个数据点，用户都可以定位到更详细的视图。</p>
		<div style="WIDTH: 470px">
				<img height="262" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig08.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 8. Summary </b>
						<b>视图</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<em>Functions </em>
				<em>视图</em>
		</p>
		<p>Functions 视图显示在应用程序的执行过程中调用的全部函数，这些函数存在于由该应用程序引用的所有模块之中，如图 9 所示。该视图显示的信息取决于所用的分析方法（采样与使用仪器）。</p>
		<div style="WIDTH: 450px">
				<img height="111" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig09.gif" width="450" border="0" />
				<br />
				<p class="figureCaption">图 9. Functions 视图</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<em>Caller/Callee </em>
				<em>视图</em>
		</p>
		<p>Caller/Callee 视图提供在 Functions 视图中所列函数的详细信息，如图 10 所示。</p>
		<div style="WIDTH: 470px">
				<img height="60" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig10.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 10. Caller/Callee </b>
						<b>视图</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<em>Callstack </em>
				<em>视图</em>
		</p>
		<p>Callstack 视图使用户能够向下搜索特定的调用跟踪，并分析哪些跟踪对性能的影响最大。</p>
		<div style="WIDTH: 470px">
				<img height="103" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vsts-dev-fig11.gif" width="470" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 11. Callstack </b>
						<b>视图</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>
				<em>Type </em>
				<em>视图</em>
		</p>
		<p>Type 视图提供有关某个特定类型的实例数量和总字节数的信息，如图 12 所示。</p>
		<p>
				<em>命令行支持</em>
		</p>
		<p>可以通过命令行工具使用性能工具功能。这为用户提供了灵活性，用户既可以从命令行运行这些工具，又可以通过脚本来使用它们，以便自动执行任务。</p>
<img src ="http://www.cppblog.com/mzty/aggbug/8630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-06-16 12:16 <a href="http://www.cppblog.com/mzty/archive/2006/06/16/8630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单元测试小技巧</title><link>http://www.cppblog.com/mzty/archive/2006/06/16/8628.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 16 Jun 2006 03:53:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/06/16/8628.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/8628.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/06/16/8628.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/8628.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/8628.html</trackback:ping><description><![CDATA[
		<h1>单元测试小技巧</h1>
		<h2 class="subtitle">编写可维护的节省时间和精力的单元测试</h2>
		<div class="date">发布日期： 2006-04-17<span class="datePipe"> | </span>更新日期： 2006-04-17</div>
		<div class="overview">
				<p>这篇文章描述了：</p>
				<table cellspacing="0" cellpadding="0" border="0">
						<tbody>
								<tr>
										<td class="listBullet" valign="top">•</td>
										<td class="listItem">
												<p>单元测试的信任</p>
										</td>
								</tr>
								<tr>
										<td class="listBullet" valign="top">•</td>
										<td class="listItem">
												<p>测试正确事件</p>
										</td>
								</tr>
								<tr>
										<td class="listBullet" valign="top">•</td>
										<td class="listItem">
												<p>创建维护测试</p>
										</td>
								</tr>
								<tr>
										<td class="listBullet" valign="top">•</td>
										<td class="listItem">
												<p>创建易读测试</p>
										</td>
								</tr>
						</tbody>
				</table>
				<p>这些天有很多的关于单元测试的和在不同的场景下为他们的应用程序编写单元测试(起始于, 我们2005年六月的 <i>MSDN</i><sup>®</sup><i>Magazine</i> 中有关测试你的数据层的文章, <em>Know Thy Code: Simplify Data Layer Unit Testing using Enterprise Services</em>)的讨论。这些意味着有很多的开发者自言自语（或者对于他们的团队）到：“哎，我们也需要开始编写测试了！”因此他们开始编写单元测试上面的单元测试直到他们达到了一个测试自己已经成为问题的程度。或许维护他们是一个太过困难，花费太长时间，或者他们并没有足够的易读性以便于理解，更或者他们本身存在bugs有一点是能够使得我们的开发人员可以下定决心去做的，那就是： 花费他们宝贵的时间以用来改进提高他们的测试或者忽略其中的问题, 从而有效的甩掉那些艰苦的工作。而这些困难的原因仅仅是因为那些不熟练的写入单元测试。.在这篇文章中，我将为大家带来在过去一年多时间里我在开发，提供咨询和培训开发者等方面有总结出来的一些最重要的练习和试验。这些小的技巧可以帮助您写出更有效的，可维护，和鲁棒性更好的单元测试。同时我希望这些总结和忠告可以帮助您避免一些由于错误引起的大量的时间的消耗。</p>
		</div>
		<center>
				<img title="" height="6" alt="*" src="http://img.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif" width="30" border="0" />
		</center>
		<div style="HEIGHT: 18px">
		</div>
		<h5 style="PADDING-TOP: 2px">本页内容</h5>
		<table style="MARGIN-TOP: 7px; MARGIN-BOTTOM: 12px" cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EQB">
												<img height="9" alt="单元测试的信任" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EQB">
												<font color="#002c99">单元测试的信任</font>
										</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EDC">
												<font color="#002c99">
														<img height="9" alt="测试正确的事情" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
												</font>
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EDC">
												<font color="#002c99">测试正确的事情</font>
										</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EZD">
												<font color="#002c99">
														<img height="9" alt="创建维护测试" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
												</font>
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EZD">
												<font color="#002c99">创建维护测试</font>
										</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EQF">
												<font color="#002c99">
														<img height="9" alt="创建易读性测试" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
												</font>
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#EQF">
												<font color="#002c99">创建易读性测试</font>
										</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#ELG">
												<font color="#002c99">
														<img height="9" alt="在你的设置方法中避免部分相关的代码" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
												</font>
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#ELG">
												<font color="#002c99">在你的设置方法中避免部分相关的代码</font>
										</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#E2G">
												<font color="#002c99">
														<img height="9" alt="总结" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
												</font>
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#E2G">
												<font color="#002c99">总结</font>
										</a>
								</td>
						</tr>
				</tbody>
		</table>
		<a name="EQB">
		</a>
		<h2>单元测试的信任</h2>
		<p>在这个部分，我将略述出一些最通用的信任，这些信任来自于在使用大量单元测试获得的好处和解释为什么这些信任通常不是必须真实的。然后我们会帮助您在您的工程中拥有这些信任。</p>
		<p>
				<b>更加简单的跟踪</b>
				<b>Bug</b>  当然这并不是必须的，那么您怎么知道您的测试是正确的？ 是否存在在一些测试环节测试失败的情况？另外您又如何知道您的测试覆盖了系统中多少的代码量？是否测试到了程序中的错误，错误又在哪里等等的问题。</p>
		<p>当你在你的单元测试中发现了bug后又会发生什么事情哪？你会突然间得到很多与愿意错误的反馈，bug被发现，但是问题并不在你测试的代码中。你的测试的逻辑存在一个bug，因此测试失败了。这些bug也是您最难被检查出来的，因为您通常会去检查您的应用程序而不会去检测你的测试环节。在这部分中，我会展示给你如何确认大量的单元测试，事实上就是使得跟踪bug变得更加容易。</p>
		<p>
				<b>代码更加便于维护</b> 从最终点考虑，你可以倾向于认为这些信任并不是必须的，当然你是对的，让我们去说，代码中每个逻辑方法至少要有一个测试方法（当然，你可能拥有一个以上的方法）在一个好的测试覆盖的工程中，大概有百分之六十的代码是能够得到单元测试的，现在不得不考虑到测试也是要被维护的，如果针对一个复杂的逻辑方法你有20个测试，那么当你向这个方法添加一个参数时会发生什么事情哪？测试无法编译。当你修改了类的结构的时候同样会发生这样的事情。这时你突然发现为了能让你的应用程序继续工作你自己需要改变大量的测试。当然这会花费你大量的时间。</p>
		<p>为了使这个信任确认下来，你需要确认你的测试是便于维护的。保持DRY规则写入：不要重复你自己。我们将更加接近的来看这个问题。</p>
		<p>
				<b>代码更加容易被理解</b>  单元测试的好处通常并非是人们最初所期待的，在一个工程中考虑修改一些你之前从没有看过的代码(比方说,一个特殊的类或者方法).你将如何动手处理这些代码？你可能需要在项目中去浏览这些特定的类或者方法使用的代码，理所当然，单元测试就是这样例子的一个很好的场所。同时，当正确写入的时候，单元测试可以为工程提供一个API文件的容易读取的设置，使得文档的处理和代码的理解对于整个团队中的新老开发者一样的简单，便捷。然而，这些只能在测试是易读的和容易理解的情况下才能被确认，这个规则很多的单元测试开发者并不会遵循。我将详述这个信任，然后在这篇文章的易读测试的部分给你展现如何在去写易读的单元测试。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<font color="#002c99">返回页首</font>
				</a>
		</div>
		<a name="EDC">
		</a>
		<h2>测试正确的事情</h2>
		<p>新来者在Test Driven Development (TDD)中一个最通常的错误就是他们通常会搞混"Fail by testing something illogical."中的"Fail first"要求。例如，你可以用下面的规格开始这个方法：</p>
		<pre class="codeSample">' returns the sum of the two numbers
Function Sum(ByVal a As Integer, ByVal b As Integer) As Integer
</pre>
		<p>你可以向如下的方式写一个失败测试：</p>
		<pre class="codeSample">&lt;TestMethod()&gt; _
Public Sub Sum_AddsOneAndTwo()
    Dim result As Integer = Sum(1, 2)
    Assert.AreEqual(4, result, "bad sum");
End Sub
</pre>
		<p>初看上去这个处理像是一个写失败测试的好的方法，它完全错失了你写错误测试的初始点。</p>
		<p>一个失败测试验证了在代码中存在一些错误，当你的测试完成后这个测试应该是通过的，现在的例子中，无论如何，测试都将会失败，即使是代码完成，因为测试逻辑上不是正确的。如果希望测试通过测需要测试自身进行修改――而不是程序的代码的改变（当程序代码改变的时候，是test-first规划的意图）简短来说，这个测试不会反映出程序代码完成后的最终的结果，因此这个不是一个好的测试。</p>
		<p>TDD中一个好的测试要求你去修改代码，从而使它能够按照想要的方式工作，这一点要胜于强迫你去反映现在的真实情况或者一个非逻辑要求的渴望的结果。例如，当1＋1返回0时就意味着测试失败。这个简单的例子和这种情况是相似的，在练习中，如果现在的需求是在工作的，测试应该可以反映你所期待的结果，然后你可以调整现在代码的情况去通过这个测试。</p>
		<p>作为一个规则，一个已经调通的测试不应该被移除掉，因为这个测试在维护工作中可以用于恢复测试。他们在你改变代码时用来确定你没有损害到现在已经工作的函数。这就是为什么你不应该修改那些已经通过的测试，除非是一些很小的修改，例如增加它的可读性（换句话说，分解测试）</p>
		<p>
				<b>当一个测试非正常失败</b>  有时你可能遇到失败的测试，而这时你对代码的改变是完全合理的。这通常是因为你遇到了冲突的需求。一般来说，可能是一个新的需求（一个改变的特性）与一个旧的可能已经不再有效的需求发生了冲突。这有两种可能：</p>
		<table class="numberedList" cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td class="listNumber" nowrap="" align="right">
										<p>1.</p>
								</td>
								<td>
										<p>在旧的需求或者无效或者在别处测试的情况下删除被验证本质上不再有效的失败的测试</p>
								</td>
						</tr>
						<tr valign="top">
								<td class="listNumber" nowrap="" align="right">
										<p>2.</p>
								</td>
								<td>
										<p>改变旧的测试使你可以测试新的要求（本质上使用新的测试），然后在新的设置下（测试的逻辑状态相同，但是初始功能函数可能有所不同）测试旧的需求。</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>而有时候一个测试在使用不完整的技术去完成任务的时候也是有效的，例如，你有一个成员类带有一个FOO方法，它表现为某几种行为，它已经经由Test在X年前测试完成，然后现在一些其他的需求加了进来，方法的逻辑增强了，从而可以去处理一些类似于在获取数据时丢失一些参数的异常处理。但这时，突然Test X失败了，虽然在测试这个函数的时候只是使用了同样的类。这个测试的失败是因为在调用方法之前丢失了一些初始处理步骤。</p>
		<p>这并不意味着你需要移除Test X，你将丢失对于一些重要功能的测试，这时你应该去关心那些初始化时的问题，而不是改变类的创建以用来适应你新的意图。</p>
		<p>当然如果你那里有200个测试都是因为旧的结构导致的失败，你就应该找到这个问题来维护你的测试。这就是为什么你应该总是移除你测试中的副本尤其是在生产代码中。</p>
		<p>
				<b>测试覆盖和测试</b>
				<b>Angles</b>  你如何知道是否你的新代码是一个好的覆盖？当试图移动一个链接或者一个约束检查后，如果所有的测试依然通过，那么你就没有足够的代码复制然后你可能需要添加其他的测试单元。</p>
		<p>确认你添加正确测试的最好方法就是测试一些最平常的行和检查直到用非常的手段使它出错。这个也许很难，但是如果你不能考虑出一个让代码出错的方法，你就可能没有好的理由在最初的地方写下这行代码。</p>
		<p>你不知道什么时候下一个开发者会试图运行你的程序，他可能优化或者错误的删除一些包含本质的行。如果你没有一个测试，它就会失败，其他的开发者可能不会知道他们犯了错误。</p>
		<p>你也可能试图利用一些常量去替代一些已经通过了的测试中调用的各种各样的参数，例如，看下面的方法：</p>
		<pre class="codeSample">Public Function Sum(ByVal x As Integer, ByVal y As Integer, _
        ByVal allowNegatives As Boolean) As Integer
    If Not allowNegatives Then Throw New Exception()
    Return x + y
End Function
</pre>
		<p>你可以打乱代码去测试覆盖，这有一些关于如何测试的变化：</p>
		<pre class="codeSample">' Try this...
If Not True Then ' replace flag with const
    If x &lt; 0 OrElse y &lt; 0 Then Throw New Exception()
End If

' Or this...
If Not allowNegatives Then
    ' replace check with const
    If False OrElse y &lt; 0 Then Throw New Exception()
End If
</pre>
		<p>如果所有的测试依然通过，那么你缺少了一个测试，另外一个红色标志是在你为多种相同值测试的检查。如下：</p>
		<pre class="codeSample">Assert.AreEqual(3, retval)
</pre>
		<p>一些方法的关系只看一次（在一个测试中）意味着你可以安全的返回3作为一个值，然后所有的针对这个方法的测试都将通过，这个当然意味着你丢失了一个测试。如果你在单元测试中检查一下代码，它就很容易被检查出来。</p>
		<p>确保你的测试写的越简单越好，一个单元测试一般不包括一个if switch或者其他任何的逻辑声明。如果你发现你自己在你的测试中写了一些类似于逻辑声明的东西，这是一个好的机会来测试一个以上的事件，在做这样的操作的时候，你会使得你的测试比读和维护更加的困难，在生产代码中同样如此。保持你的测试简单，你在生产代码中发现bug要胜于在你的单元测试中。</p>
		<p>
				<b>使测试易于运行</b>  如果你的测试并不容易运行，那么人们不会信任它。你的应用程序最有可能有下面两种类型的测试：</p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>测试在没有任何配置的情况下平稳的运行（这种类型的测试，我们可以在任何的机器上，在代码的最终版上或者在源控制上测试，并且做到没有任何故障的测试）</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>在运行前需要一些配置.</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>第一种类型是你应该模仿的，第二种类型是你通常做的，尤其你如果你是一个新的单元测试。如果你发现你自己测试时有很多的特殊的需求，现在是正常的，但是重要的一点就是你要隔离出两个组让他们能够单独的去做测试。</p>
		<p>我们的想法是任意一个开发者都应该有能力修改和运行一些不需要设置特殊的配置的测试进行测试。如果这有一些测试需要在运行前有特殊的关注，开发者应该知道他们，然后他可以花一些时间学习这些测试的方法。因为很多的开发者比较的懒（当然，不是你），你可以设想，他们不会去做那些特殊的设置，相反，他们会让测试失败因为他们有更好的事情去做。</p>
		<p>当用户让测试失败时，他们开始考虑他们不能够信任这些测试了。很难说是否测试可以在一个中找到一个正式的bug或者只是一个错误的定位。开发者可能不明白为什么测试者会在一开始就执行失败。一旦他们不再信任你的测试，开发者将会停止运行它们，那么bug就会驻留在程序中，之后一连串的麻烦就来了。。。</p>
		<p>
				<b>为了避免这件事情，确认你总是有一个组准备好了去测试，测试程序则是可以安全运行，可信任的。把那些属于配置挑战组的测试放到不同的文件夹，树或者工程中，同时标记特殊的说明指明他们在运行前需要做什么。完成这些后，开发者可以不投入时间去配置就开始测试工作。当他们有时间和需要时，他们也可以配置，运行更多的测试环节。</b>
		</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<font color="#002c99">返回页首</font>
				</a>
		</div>
		<a name="EZD">
		</a>
		<h2>创建维护测试</h2>
		<p>我们应该试着避免测试私有或保护成员。这篇文章也许能够帮助一些人解决一部分问题，但是我很坚决相信百分之九十九的时间，你可以全面的测试一个类，通过编写一些与它的独立公共接口相反的单元测试。测试私有成员可以使你的测试更加脆弱，如果这个需要被测试的类的一些内在方面略有改动的话。你应该使用通过调用一些代码里别处的公共功能这一方法去测试私有功能。当你依然能够确定全部功能并没有改变的时候，仅仅测试公共成员会导致测试遭受常量代码的因式分解以及内部的执行情况改变。</p>
		<p>
				<b>在可能的时候，应该重新使用你的创造物，处理过程，和声明代码。不要在一个单元测试中直接的创建类的实例。如果你在任何并不包含在此单元测试框架中的类前面看到这个单词“</b>new”，你应该考虑一下将你创造的代码放在一个特殊的整体方法之中，它可以为你创建一个对象实例。你可以到时再重新使用这个方法来获得你的测试在其他测试之中的最新实例。这样可以帮助你来保持这个测试维护所需的时间，然后在测试进行的时候，从对代码无法预料的改变之中保护你的测试。作为一个例子，<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig1" target="_blank"><b><font color="#002c99">Figure 1</font></b></a>展示了一对简单的测试，它使用了一个Calc类。</p>
		<p>假设你有20，或者你甚至有100，与Calc类做相反测试，所有这些看起来令人吃惊的相似。现在一个计划的改变迫使你不得不删除默认的Calc构造器并且使用一个含有一些参数的不同的构造器。马上，你所有的测试就被暂停了。你可能可以很轻易的发现问题的关键并修复它，但你也可能做不到。最主要的问题是你将会浪费很多宝贵时间在修理你的测试上面。如果你在你的测试类之中使用一个整体的方法去创建Calc 实例，就像<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig2" target="_blank"><b><font color="#002c99">Figure 2</font></b></a>所显示的那样，这些就并不是个问题。</p>
		<p>我已经对测试做了一些改变已使它们能够具有更多可维护性。首先，我将新创建的代码迁移至可以再度使用的整体方法之中。这就意味着我只需仅仅改变一个简单的方法以使得在这个测试类中的所有测试在一个新的构造器中的能够正常的工作。另外一个为创造问题而设的简单解决方法是把创作物迁移到测试类的&lt;TestInitialize()&gt;方法之中。不幸运的是，这个能够很好的工作仅仅在你重新使用一个对象并在一些测试中把它当作一个局部类变量。如果你仅仅为一些测试使用它（部分相关成员），你倒不如在测试中将它们实例化，并且使它们更具易读性。</p>
		<p>顺便一提的是，请注意，我已经将方法命名为Factory_CreateDefaultCalc 。我很喜欢将我测试中的任何帮助方法用特殊的前缀来命名，这样我就能很轻易的掌握它是做什么用的。这样对易读性也是非常有帮助的。</p>
		<p>我的第二个改变是重新使用测试中的声明代码，并将这段代码迁移到一个确认方法之中。所谓确认方法是你测试中的一个可再度使用的方法， 这个方法包含了一个声明语句但是它可以接受不同输入和在输入的基础上进行校验。当你在不同输入或者不同的初始状态下一次又一次的声明同一事物时，你可以使用确认方法。这一方法的优点是既使在一个不同的方法里面声明，如果这个声明失败了你将可以继续保有一个异常处理，而且原始调用测试将会显示在测试失败输出窗口之中。</p>
		<p>我也在Calc 中传递实例而不是使用一个局部变量，因此我知道我经常传递一个实例，而且这个实例是调用测试将其初始化的。当你想要改变对象状态时你可能想要做同样的事情，举个例子来说，当在测试下或者在将会传递给测试的对象下配置特殊对象时，可以使用特殊的Configure_XX方法。这些方法应该能够解释他们配置一个对象将会用来做什么用。<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig3" target="_blank"><b><font color="#002c99">Figure 3</font></b></a>之中的代码就是以上方法的实例。</p>
		<p>这个测试拥有很多设置代码可以用来处理向注册管理器对象中添加初始状态，它是这个测试类之中的成员。在此的确也有一些重复。<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig4" target="_blank"><b><font color="#002c99">Figure 4</font></b></a>显示了在初始代码之外这些事例在因式分解之后将会如何变化。</p>
		<p>修订测试具有非常高的可读性和稳定性。仅仅需要注意的是不要那么的refactor你的测试，他们可能会以一个单一的，不可读的代码行作为结束。应该注意的是我在这里可能依然使用一个Verify_XX 方法，但是这并不是我真正要在这里加以说明的。</p>
		<p>
				<b>消除测试之间的依赖关系</b>
		</p>
		<p>一个测试应该能够自我独立。它不应该与其他测试相关联，也不应该依赖任何具有特殊运行顺序的测试，它应该能够获得你所写的所有测试，可以随意运行所有测试或者只运行其中的一部分，并且是以任何顺序，而且要能够确保它们无论怎样都应该正确的运行。如果你不能够执行这个规则，你将会只在某种特殊的情况下按照预期的表现来运行的状况下结束你的测试。这样子的话，当你在最终期限下与此同时你还想确定你没有向系统之中引进新的问题的时候，当然就会出现问题。你可能很困惑而且考虑着是不是你的代码出现问题，这时，在事实上，问题其实仅仅是你的测试运行顺序所引起的。因此，你可能开始错过了一些在测试中失败的结果而且使它越写越少。这将会是个长期的过程。</p>
		<p>如果你从一个测试调出至另一个测试之中，你应该在它们之间创建一个从属关系。你本质上说是在一个测试中测试两个事物（我将会在下一章中解释为什么这会成为一个问题）。就另一方面来说，如果你有测试B，它与测试A 所产生的状态是不相关的，那么你会陷入“顺序”陷阱之中。如果你或者其他人想要改变测试A，测试B将会暂停而且你不知它暂停的原因。对这些故障进行故障处理会浪费很多时间。</p>
		<p>使用&lt;TestInitialize()&gt; 和&lt;TestCleanup()&gt;方法是本质上能够获得更好的测试隔离。确定你的测试数据时刻是最新的，而且测试下对象的也具有新的实例，而且所有的状态可以提前预知，而且无论你的测试在任何地方或者任何时间被运行，运行的情况都是相同的。</p>
		<p>
				<b>在一个单独单元测试中避免多重声明</b>
		</p>
		<p>我们将声明故障看作一个程序弊病的象征且声明被当作软件体的指示点或者“血液检查”。你可以找到越多的症状，程序弊病就越可以轻松的被诊断和排除掉。如果你在一个测试中定义了多重声明，只有第一个故障声明将会以抛出异常的方式显示出来。请参考下面插图之中的测试代码：</p>
		<pre class="codeSample">&lt;TestMethod()&gt; _
Public Sub Sum_AnyParamBiggerThan1000IsNotSummed()
    Assert.AreEqual(3, Sum(1001, 1, 2)
    Assert.AreEqual(3, Sum(1, 1001, 2) ' Assert fails
    Assert.AreEqual(3, Sum(1, 2, 1001) ' This line never executes
End Sub
</pre>
		<p>
				<b>你可能没有发现以上代码之中其他可能的征兆。在一个故障之后，并发的声明不会被执行。这些不能生效的声明可能提供了有价值的数据（或者征兆）可能能够帮助你很快的集中的焦点而且发现潜在的问题。因此在一个独立的测试中运行多重声明增加了具有很少价值复杂性。另外，声明应该被独立的运行，我们应该设置自我独立的单元测试以使得你具有能够很好的发现错误的机会。</b>
		</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<font color="#002c99">返回页首</font>
				</a>
		</div>
		<a name="EQF">
		</a>
		<h2>创建易读性测试</h2>
		<p>如果你以前写过单元测试，你是否在单元测试上写了一个好的声明行？可许不是这样的，大多数开发者并不厌烦去写一个好的声明因为他们更加关心去写测试。</p>
		<p>假设你是团队中的一个新的开发者，你试图读一个单元测试。连接这个：</p>
		<pre class="codeSample">&lt;TestMethod()&gt; _
Public Sub TestCalcParseNegative()
    Dim c As New Calc
    Assert.AreEqual(1000, c.Parse("-1, -1000")
End Sub
</pre>
		<p>作为一个简单的练习，如果你理解了上例中Calc分列方法的用法，你很可能可以进行很好的推测，但是他可以简单的作为人员数量的用例使得输出结果为1000:</p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>在组中返回最大的负数作为一个正数。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>如果数字是负数且返回值为剩下几个数的总和作为一个正数，那么忽略第一个数字。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>返回相互作乘积运算而得的数字。</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>现在请参考下面在单元测试之中的小改动：</p>
		<pre class="codeSample">&lt;TestMethod()&gt; _
Public Sub Parse_NegativeFirstNum_ReturnsSumOfTheRestAsPositive()
    Dim c As New Calc
    Dim parsedSumResult As Integer = c.Parse("-1", "-1000")
    Const SUM_WITH_IGNORED_FIRST_NUM As Integer = 1000
    Assert.AreEqual(SUM_WITH_IGNORED_FIRST_NUM, parsedSumResult)
End Sub
</pre>
		<p>
				<b>这个是不是比较容易理解呢？当声明消息消失之后，表达意图最合适的地方就是测试的名字。</b> 如果你广泛的使用了它，你将会发现你不再需要读测试代码就能明白代码测试的目的所在。事实上，你经常根本不需要写任何注释，因为代码，特别是那些带着实例的，他们自己是证明自己的。</p>
		<p>名字包含了三部分内容： 测试下方法的名字（解析），测试下的状态或者规则（带着第一个负数传递一个字符串），以及预期的输出或者运行情况（剩余数字的总和以一个正数的形式返回）。需要注意的是我从名称中将Test以及Calc这两个词删除。我已经知道这是一个属性的测试因此在此没有重复此信息的必要。我也知道这是一个在Calc类中的测试因为测试类经常是写给一个特殊类的（这个类也许已经被命名为CalcTests）。</p>
		<p>名字也许会很长，但是又有谁在乎呢？它读起来更像是一个标准英语的句子而且它使得一个新来的开发者更容易明白测试的内容。更是这样，当这个测试发生故障时，我们甚至不需要调试代码就可以知道问题究竟出在哪里。</p>
		<p>需要注意的是，我已经在前面分别实际演示了通过在不同行中创建一个结果变量的方法从声明操作中进行分解操作。这样做至少有两个理由。第一个理由是，你可以为一个变量分配一个可读性强的名字，它可以包含结果，这样可以使你的声明行非常易于理解以及易于读。第二点是，测试下与对象相反的invocation 可能非常的长，它可能会使你的声明行延伸出屏幕的边缘之外，这样导致测试者向右滚屏。就我个人而言，我认为这个是非常恼人的。</p>
		<p>我在我的测试中使用了很多常量以确保我的声明读起来像一本书。在先前的例子之中，你可以读到声明中说：“确保分解总数是与忽略第一个数后所得总和是相等的。” 为你的变量取一个很好的名字能够在某些程度上弥补对于测试的命名不足。</p>
		<p>
				<b>当然，有时一个声明</b> 消息是在一个单元测试中传递intent的最好的方法。 一个好的声明消息始终能够解释什么因该会发生或者什么发生了而且为什么会出错。举个例子来说，“分列应该忽略掉第一个数字如果这个数字是个负数的话”，“分列不能够忽略掉第一个负数”，还有“X调用对象Y标记错误”这些都是有用的声明消息，它们很清晰的描述了结果的情况。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<font color="#002c99">返回页首</font>
				</a>
		</div>
		<a name="ELG">
		</a>
		<h2>在你的设置方法中避免部分相关的代码</h2>
		<p>一个&lt;TestInitialize()&gt; 方法是样例成员变量在测试中使用的一个好地方。你所有的测试，只有在一部分的测试中避免变量。他们可以为测试设置本地变量。如果你创建了部分相关的实例作为类的成员，用来在测试中简单的避免创建的副本，你应该使用在文章前面解释的工厂方法，使用部分相关变量使得你的代码和设置方法缺少易读性。一旦变量在一个或者每个测试中使用，那么他应该是&lt;TestInitialize()&gt; 方法的一个成员和变量。</p>
		<p>
				<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig5" target="_blank">
						<b>
								<font color="#002c99">Figure 5</font>
						</b>
				</a> 展现了一个拥有两个成员变量的类的测试。但是他们中的一个(cxNum)只被部分使用。<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx?fig=true#fig6" target="_blank"><b><font color="#002c99">Figure 6</font></b></a> 展现了如何在测试中替换代码从而使它更加易读的方法。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/UnitTestingTips.mspx#top">
						<font color="#002c99">返回页首</font>
				</a>
		</div>
		<a name="E2G">
		</a>
		<h2>总结</h2>
		<p>就像你所看到的，写单元测试并不是一个微不足道的任务，如果步骤正确，单元测试可以为开发者的生产力和代码的质量带来令人惊讶的提高，他可以帮助你去创建的应用程序含有更少的错误，同时也可以便于其他的开发者去洞察你的代码，但是他也需要在之前承担一个义务，确认遵循一些简单的规则。当方法并不是很好时，单元测试则可能达到一个相反的结果，从而浪费您的时间，并且使测试过程更加复杂。</p>
		<p>
				<b>Roy Osherove</b> Agile组的负责人, 这个顾问公司致力于agile software development 和 .NET architecture的研究工作. Roy同时维护了一个blog在<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/www.iserializable.com" target="_blank"><font color="#002c99"> www.iserializable.com</font></a>上有相关的信息. 你可以通过Email联系他： <em>Roy@TeamAgile.com</em>.</p>
		<p>
				<a href="http://msdn.microsoft.com/msdnmag/issues/06/01/UnitTesting/default.aspx" target="_blank">
						<font color="#002c99">转到英文页面</font>
				</a>
		</p>
<img src ="http://www.cppblog.com/mzty/aggbug/8628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-06-16 11:53 <a href="http://www.cppblog.com/mzty/archive/2006/06/16/8628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Visual Studio 2005 Team System 进行单元测试</title><link>http://www.cppblog.com/mzty/archive/2006/06/16/8626.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 16 Jun 2006 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/06/16/8626.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/8626.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/06/16/8626.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/8626.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/8626.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码						发布日期： 11/10/2005 | 更新日期： 11/10/2005						Scott DockendorfTelligent Systems, Inc.				适用于：Microsoft Visual Studio ...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2006/06/16/8626.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/8626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-06-16 11:50 <a href="http://www.cppblog.com/mzty/archive/2006/06/16/8626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用 Visual Studio Team Test 进行单元测试</title><link>http://www.cppblog.com/mzty/archive/2006/06/16/8624.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Fri, 16 Jun 2006 03:46:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/06/16/8624.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/8624.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/06/16/8624.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/8624.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/8624.html</trackback:ping><description><![CDATA[
		<h1>演练：使用 Visual Studio Team Test 进行单元测试</h1>
		<h2 class="subtitle">
		</h2>
		<div class="date">发布日期： 5/24/2005<span class="datePipe"> | </span>更新日期： 5/24/2005</div>
		<div class="overview">
				<p>Mark Michaelis<br />Itron Corporation</p>
				<p>
						<b>摘要：</b>本演练通过测试驱动开发 (TDD) 和先测试-后编码 (test-then-code) 的方法学习单元测试。</p>
		</div>
		<center>
				<img title="" height="6" alt="*" src="http://img.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif" width="30" border="0" />
		</center>
		<div style="HEIGHT: 18px">
		</div>
		<h5 style="PADDING-TOP: 2px">本页内容</h5>
		<table style="MARGIN-TOP: 7px; MARGIN-BOTTOM: 12px" cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#E4B">
												<img height="9" alt="简介" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#E4B">简介</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EGD">
												<img height="9" alt="开始" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EGD">开始</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EAF">
												<img height="9" alt="创建测试" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EAF">创建测试</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EVCAC">
												<img height="9" alt="运行测试" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EVCAC">运行测试</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EHGAC">
												<img height="9" alt="检查异常" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EHGAC">检查异常</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EXIAC">
												<img height="9" alt="从数据库中加载测试数据" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EXIAC">从数据库中加载测试数据</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EJJAC">
												<img height="9" alt="测试视图 (Test View) 窗口" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EJJAC">测试视图 (Test View) 窗口</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EMLAC">
												<img height="9" alt="增加一个测试数据库" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EMLAC">增加一个测试数据库</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#E2OAC">
												<img height="9" alt="将数据与测试关联" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#E2OAC">将数据与测试关联</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EGDAE">
												<img height="9" alt="实现和重构目标方法" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EGDAE">实现和重构目标方法</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EDEAE">
												<img height="9" alt="代码覆盖" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EDEAE">代码覆盖</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EXEAE">
												<img height="9" alt="初始化和清除测试" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EXEAE">初始化和清除测试</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EHHAE">
												<img height="9" alt="最佳实践" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EHHAE">最佳实践</a>
								</td>
						</tr>
						<tr valign="top">
								<td>
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EAIAE">
												<img height="9" alt="小结" hspace="4" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width="7" vspace="2" border="0" />
										</a>
								</td>
								<td class="onThisPage">
										<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#EAIAE">小结</a>
								</td>
						</tr>
				</tbody>
		</table>
		<a name="E4B">
		</a>
		<h2>简介</h2>
		<p>最新发布的 Visual Studio Test System (VSTS) 包含了一套用于 Visual Studio Team Test 的完整功能。Team Test 是 Visual Studio 集成的单元测试框架，它支持：</p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>测试方法存根 (stub) 的代码生成。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>在 IDE 中运行测试。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>合并从数据库中加载的测试数据。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>测试运行完成后，进行代码覆盖分析。 </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>另外，Team Test 包含了一套测试功能，可以同时支持开发人员和测试人员。</p>
		<p>在本文中，我们准备演练如何创建Team Test 的单元测试。我们从一个简单的示例程序集开始，然后在该程序集中生成单元测试方法存根。这样可以为Team Test 和单元测试的新手读者提供基本的语法和代码，同时也很好地介绍了如何快速建立测试项目的结构。然后，我们转到使用测试驱动开发 (test driven development, TDD) 方法，即在写产品代码前先写单元测试。</p>
		<p>Team Test的一个关键特点是从数据库中加载测试数据，然后将其用于测试方法。在演示基本的单元测试后，我们描述如何创建测试数据并集成到测试中。</p>
		<p>本文中使用的示例项目包含一个 LongonInfo 类，它封装了与登录相关的数据（例如用户名和密码）以及一些关于数据的简单的验证规则。最终的类如下图 1 所示。</p>
		<div style="WIDTH: 152px">
				<img height="239" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig1.gif" width="152" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b>
						</b>
						<b>1. </b>
						<b>最终的</b>
						<b>
						</b>
						<b>LogonInfo</b>
						<b>
						</b>
						<b>类</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>请注意所有的测试代码位于一个单独的项目。这是有道理的，产品代码应该尽可能少的受测试代码影响，所以我们不想在产品代码的程序集中嵌入测试代码。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EGD">
		</a>
		<h2>开始</h2>
		<p>首先，我们创建一个名为“VSTSDemo”的类库项目。默认情况下，<b>为方案创建目录</b><b></b>(<b>Create directory for solution</b><b>) </b>复选框被选中。保留此选项可以使我们在 VSTSDemo 项目的同一层目录创建测试项目。相反，如果不选中此选项，Visual Studio 2005 会将测试项目放在 VSTSDemo 项目的子目录中。测试项目遵循 Visual Studio 在解决方案文件路径的子目录中创建额外项目的规定。</p>
		<p>创建初始的 VSTSDemo 项目后，我们使用 Visual Studio 的解决方案资源管理器将 Class1.cs 文件重命名为 <i>LogonInfo.cs</i>，这样类名也会被更新为 <b>LogonInfo</b>。然后我们修改构造函数以接受两个字符串参数：<b>userId</b> 和 <b>password</b>。一旦构造函数的签名被声明，我们就可以为构造函数生成测试。</p>
		<div style="WIDTH: 356px">
				<img height="469" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig2.gif" width="356" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b>
						</b>
						<b>2. </b>
						<b>LongonInfo </b>
						<b>构造函数的上下文菜单的“创建测试</b>
						<b>…</b>
						<b>”</b>
						<b> (</b>
						<b>Create Tests...</b>
						<b>) </b>
						<b>菜单项</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EAF">
		</a>
		<h2>创建测试</h2>
		<p>在开始编写 <b>LogonInfo</b><b></b>的任何实现之前，我们遵循 TDD 实践的规则，首先编写测试。TDD 在Team Test 中并不是必需的，但最好在本文的剩余部分遵循 TDD。右键单击 <b>LogonInfo()</b><b></b>构造函数，然后选择“创建测试…”菜单项(如图 2 所示)。这样会出现一个对话框，可以在不同的项目中生成单元测试（如图 3 所示）。默认情况下，项目设置的输出 (Output) 选项是一个新的 Visual Basic 项目，但是也可以选择 C# 和 C++ 测试项目。在本文中，我们选择 Visual C#，然后单击 <b>OK </b>按钮，接着输入项目名 <i>VSTSDemo.Test</i>。测试项目名称。</p>
		<div style="WIDTH: 464px">
				<img height="433" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig3.gif" width="464" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b>
						</b>
						<b>3. </b>
						<b>生成单元测试对话框</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>生成的测试项目包含四个与测试相关的文件。</p>
		<table class="dataTable" id="EDG" cellspacing="0" cellpadding="0">
				<thead>
						<tr class="stdHeader" valign="top">
								<td id="colEFG">文件名</td>
								<td id="colEJG" style="BORDER-RIGHT: #cccccc 1px solid">目的</td>
						</tr>
				</thead>
				<tbody>
						<tr class="record" valign="top">
								<td>
										<p class="lastInCell">AuthoringTest.txt</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">提供关于创建测试的说明，包括向项目增加其他测试的说明。</p>
								</td>
						</tr>
						<tr class="evenRecord" valign="top">
								<td>
										<p class="lastInCell">LogonInfoTest.cs</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">包含了用于测试 <b>LogonInfo()</b><b></b>的生成测试，以及测试初始化和测试清除的方法。</p>
								</td>
						</tr>
						<tr class="record" valign="top">
								<td>
										<p class="lastInCell">ManualTest1.mht</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">提供了一个模板，可以填入手工测试的指令。</p>
								</td>
						</tr>
						<tr class="evenRecord" valign="top">
								<td>
										<p class="lastInCell">UnitTest1.cs</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">一个空的单元测试类架构，用于放入另外的单元测试。</p>
								</td>
						</tr>
				</tbody>
		</table>
		<div class="dataTableBottomMargin">
		</div>
		<p>因为我们不打算对该项目进行手工测试，并且由于已经有了一个单元测试文件，我们将删除 ManualTest1.mht 和 UnitTest1.cs。</p>
		<p>除了一些默认的文件，生成的测试项目还包含了对 Microsoft.VisualStudio.QualityTools.UnitTestFramework和 VSTSDemo 项目的引用。前者是测试引擎运行单元测试需要依赖的测试框架程序集，后者是对我们需要测试的目标程序集的项目引用。</p>
		<p>默认情况下，生成的测试方法是包含以下实现的占位符：</p>
		<p>
				<b>清单</b>
				<b> 1. </b>
				<b>生成的测试方法：</b>
				<b>ConstructorTest(),</b>
				<b>
				</b>
				<b>位于</b>
				<b>VSTSDemo.Test.LogonInfoTest</b>
		</p>
		<pre class="codeSample">   
/// &lt;summary&gt;
   ///This is a test class for VSTTDemo.LogonInfo and is intended
   ///to contain all VSTTDemo.LogonInfo Unit Tests
   ///&lt;/summary&gt;
   [TestClass()]
   public class LogonInfoTest
   {
      // ...

      /// &lt;summary&gt;
      ///A test case for LogonInfo (string, string)
      ///&lt;/summary&gt;
      [TestMethod()]
      public void ConstructorTest()
      {
         string userId = null; // TODO: Initialize to an appropriate value

         string password = null; // TODO: Initialize to an appropriate value

         LogonInfo target = new LogonInfo(userId, password);

         // TODO: Implement code to verify target
         Assert.Inconclusive(
            "TODO: Implement code to verify target");
      }
}
</pre>
		<p>确切的生成代码会根据测试目标的方法类型和签名不同而有所不同。例如，向导会为私有成员函数的测试生成反射代码。在这种特别的情况下，我们需要专门用于公有构造函数测试的代码。</p>
		<p>关于Team Test ，有两个重要的特性。首先，作为测试的方法由 <b>TestMethodAttribute</b><b></b>属性指定，另外，包含测试方法的类有 <b>TestClassAttribute</b><b></b>属性。这些属性都可以在 Microsoft.VisualStudio.QualityTools.UnitTesting.Framework 命名空间中找到。Team Test 使用反射机制在测试程序集中搜索所有由 <b>TestClass</b><b></b>修饰的类，然后查找由 <b>TestMethodAttribute</b><b></b>修饰的方法来决定执行的内容。另外一个重要的由执行引擎而不是编译器验证的标准是，测试方法的签名必须是无参数的实例方法。因为反射搜索 <b>TestMethodAttribute</b>，所以测试方法可以使用任意的名字。</p>
		<p>测试方法 <b>ConstructorTest()</b><b></b>首先实例化目标 LongonInfo 类，然后断言测试是非决定性的(使用<b>Assert.Inconclusive()</b>)。当测试运行时，<b>Assert.Inconclusive()</b><b></b>说明了它可能缺少正确的实现。在我们的示例中，我们更新 <b>ConstructorTest()</b><b></b>方法，让它检查用户名和密码的初始化，如下所示。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>2. </b>
				<b>更新的</b>
				<b>
				</b>
				<b>ConstructorTest()</b>
				<b>
				</b>
				<b>实现</b>
		</p>
		<pre class="codeSample">      
/// &lt;summary&gt;
      ///A test case for LogonInfo (string, string)
      ///&lt;/summary&gt;
      [TestMethod()]
      public void ConstructorTest()
      {
         string userId = "IMontoya";

         string password = "P@ssw0rd";

         LogonInfo logonInfo = new LogonInfo(userId, password);

         Assert.AreEqual&lt;string&gt;(userId, logonInfo.UserId,
            "The UserId was not correctly initialized.");
         Assert.AreEqual&lt;string&gt;(password, logonInfo.Password,
            "The Password was not correctly initialized.");
      }
</pre>
		<p>请注意我们的检查使用 <b>Assert.AreEqual&lt;T&gt;(</b><b>) </b>方法完成。<b>Assert</b><b></b>方法也支持没有泛型的 <b>AreEqual()</b>，但是泛型版本几乎总是首选，因为它会在编译时验证类型匹配 － 在 CLR 支持泛型前，这种错误在单元测试框架中非常普遍。</p>
		<p>因为 UserID 和 Password 的实例域还没有创建，我们需要回头将其添加到 <b>LogonInfo</b><b></b>类中，以便VSTTDemo.Test 项目可以编译。</p>
		<p>即使我们还没有一个有效的实现，让我们开始运行测试。如果我们遵循 TDD 方法，我们就应该直到测试证明我们需要这样的代码时才去编写产品代码。我们仅在建立项目结构时违背此原则，但是一旦项目建立后，就可以容易地始终遵循 TDD 方法。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EVCAC">
		</a>
		<h2>运行测试</h2>
		<p>要运行项目中的所有测试，只需要运行测试项目。要实现这一点，我们需要右键单击解决方案资源管理器的VSTSDemo.Test 项目，选择<b>设置为启动项目</b><b></b>(<b>Set as StartUp Project</b><b>)</b>。接着，使用菜单项<b>调试</b><b>-&gt;</b><b>启动</b><b></b><b>(</b><b>F5</b><b>) </b>或者<b>调试</b><b>-&gt;</b><b>开始执行（不调试）</b><b>(</b><b>Ctrl+F5</b><b>) </b>开始运行测试。</p>
		<p>这时出现测试结果窗口，列出项目中的所有测试。因为我们的项目只包含一个测试，因此只列出了一个测试。开始的时候，测试会处于挂起的状态，但是一旦测试完成，结果将是我们意料中的失败（如图 4 所示）。</p>
		<div style="WIDTH: 464px">
				<img height="182" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig4.gif" width="464" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 4. </b>
						<b>执行所有测试后的测试结果窗口</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>图 4 显示了<b>测试结果</b><b> (Test Results) </b>窗口。这个特别的屏幕快照除了默认的列外，还显示了错误信息。您可以在列头上单击右键并选择菜单项<b>增加</b><b>/</b><b>删除列…</b>以增加或者删除列。</p>
		<p>如果要查看测试的额外细节，我们可以选定测试并双击，打开“ConstructorTest[Results]”窗口，如图 5 所示。</p>
		<div style="WIDTH: 463px">
				<img height="300" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig5.gif" width="463" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 5. </b>
						<b>详细的测试</b>
						<b>
						</b>
						<b>ConstructorTest [</b>
						<b>Results</b>
						<b>]</b>
						<b>
						</b>
						<b>窗口</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>另外，我们可以右键单击单个测试，然后选择<b>打开测试</b><b></b>(<b>Open Test) </b>菜单项，进入测试代码。因为我们已经知道问题在于 LogonInfo 构造函数的实现，我们可以去那里编写初始化 <b>UserID </b>和 <b>Password </b><b>字段</b>的代码，使用传入的参数对它们进行初始化。重新运行测试以验证测试现在可以通过。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EHGAC">
		</a>
		<h2>检查异常</h2>
		<p>下一步是创建 <b>LongonInfo </b>类，以提供对 UserID 和 password 的一些验证。不幸的是，<b>UserID</b>和 <b>Password </b>字段是公共的，这意味着它们没有提供任何封装来确保它们有效。但是在我们将其转换为属性并提供验证前，让我们编写一些测试来验证任何实现的结果都是正确的。</p>
		<p>我们首先来编写一个测试，防止空值 (null) 或空字符串赋值给 UserID。预期结果是，如果空值传送给构造函数，会引发一个 <b>ArgumentException</b><b></b>异常。测试代码如清单 3 所示。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>3. </b>
				<b>使用</b>
				<b>
				</b>
				<b>ExpectedExceptionAttribute</b>
				<b>
				</b>
				<b>对异常情况进行测试</b>
		</p>
		<pre class="codeSample">      
[TestMethod]
      [ExpectedException(typeof(ArgumentException),
         "A userId of null was inappropriately allowed.")]
      public void NullUserIdInConstructor()
      {
         LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
      }

      [TestMethod]
      [ExpectedException(typeof(ArgumentException),
         "A empty userId was inappropriately allowed.")]
      public void EmptyUserIdInConstructor()
      {
         LogonInfo logonInfo = new LogonInfo("", "P@ss0word");
      }
</pre>
		<p>请注意对于 <b>ArgumentException</b><b></b>没有 try-catch 代码块的显式测试。不过，两个测试都包含另外一个属性 <b>ExpectedException</b>，它接受一个类型参数，以及一个可选的错误信息，用于在没有引发异常时显示。当这个单元测试执行时，测试框架会显式地监视引发的 <b>ArgumentException</b><b></b>异常，如果方法没有引发这个异常，测试将失败。运行这些测试会证明我们还没有对 UserID 做任何验证检查；因此，测试会失败，因为没有引发预期的异常。</p>
		<p>有了失败的测试，现在可以回到产品代码进行更新来提供测试需要检查的功能。在这个例子中，我们将 UserID字段转换为属性，并提供验证检查（清单 4）。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>4. </b>
				<b>在</b>
				<b>
				</b>
				<b>LogonInfo</b>
				<b>
				</b>
				<b>类中验证</b>
				<b>
				</b>
				<b>UserId</b>
		</p>
		<pre class="codeSample">   
public class LogonInfo
   {
      public LogonInfo(string userId, string password)
      {
         this.UserId = userId;
         this.Password = password;
      }

      private string _UserId;
      public string UserId
      {
         get { return _UserId; }
         private set
         {
            if (value == null || value.Trim() == string.Empty)
            {
               throw new ArgumentException(
                  "Parameter userId may not be null or blank.");
            }
            _UserId = value;
         }
      }
      
      // ...
}
</pre>
		<p>属性的实现使用了 C# 2.0 的功能，其中 getter 和 setter 的访问权限不一致。setter的实现标识为私有，而 getter 实现为公有。这样 UserID 就不能在 LogonInfo 类外被修改了（除非通过反射机制）。</p>
		<p>一旦增加了验证，我们可以重新运行测试来验证实现是正确的。我们运行所有的三个测试来验证 UserID 字段转换为属性的重构过程没有产生任何意外的错误。单元测试的真正价值在代码修改的时候才真正有所体现。一套单元测试可以保证我们在维护和改进代码的时候没有破坏代码。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EXIAC">
		</a>
		<h2>从数据库中加载测试数据</h2>
		<p>对于 <b>LogonInfo </b>类的下一次修改，我们将提供一个方法来改变密码。该方法接受旧密码和新密码作为参数。另外，我们会验证密码符合某种复杂性需求。确切的说，我们将保证密码符合 Windows Active Directory 的默认需求，即包含以下四种类型字符中的三种：</p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>大写字母 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>小写字母</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>标点符号</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>数字</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>另外，我们将检查密码最少包含 6 个字符，最多包含 255 个字符。</p>
		<p>和之前一样，我们在编写实现前先为密码复杂性需求编写测试。但是显然，我们需要提供一个测试值的大集合用于验证实现。我们不是为每个测试用例创建一个单独的测试，也不是创建一个循环来调用一系列的测试用例，我们将创建一个数据驱动测试，它从数据库中取出所需的数据。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EJJAC">
		</a>
		<h2>测试视图 (Test View) 窗口</h2>
		<p>首先我们定义一个名为 <b>ChangePasswordTest()</b> 的新测试。定义后，从菜单项<b>测试</b><b>-&gt;</b><b>查看和创建测试</b><b>(</b><b>Test-&gt;View and Author Tests</b><b>)</b>为测试方法打开<b>测试视图</b>窗口，如图 6 所示：</p>
		<div style="WIDTH: 325px">
				<img height="352" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig6.gif" width="325" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b>
						</b>
						<b>6. </b>
						<b>测试视图</b>
						<b> (</b>
						<b>Test view</b>
						<b>) </b>
						<b>窗口</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>测试视图窗口可用来运行指定的测试和浏览测试的特定属性。通过增加额外的列（右键单击列头并选择添加/删除列…），我们可以排序并根据偏好查看测试。有些列来自修饰测试的属性。例如，添加 <b>OwnerAttribute</b><b></b>将在所有者列显示测试的所有者。其它元数据属性（如 <b>DescriptionAttribute</b><b>）</b>也可以使用。这些属性都可以在 Microsoft.VisualStudio.QualityTools.UnitTesting.Framework 命名空间中找到。如果没有显式的属性存在，那么我们可以使用自由形式的 <b>TestPropertyAttribute</b><b></b>来为特别的测试方法增加名－值对。</p>
		<p>没有对应列的属性可以在一个测试的属性窗口中显示（选择一个测试，在右键上下文菜单中单击<b>属性</b>）。它包含了指定数据连接字符串和用于载入测试数据的表名的属性。显然，为了指定有效值，我们需要一个数据库连接。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EMLAC">
		</a>
		<h2>增加一个测试数据库</h2>
		<p>从服务器资源管理器窗口，我们可以使用<b>创建新的</b><b> SQL Server</b><b>数据库</b><b></b>(<b>Create new SQL Server Database</b><b>) </b>菜单项。但是要小心这种方法，如果我们要在其它计算机上执行测试的话，我们要保证在一台服务器上创建数据库，其它可能执行测试的计算机必须能够访问该服务器 — 例如一台用于构建的计算机。</p>
		<p>另外一个选择是仅仅增加一个数据库文件。使用<b>项目</b><b>-&gt;</b><b>增加新项</b><b>…</b> (<b>Project-&gt;Add new item...</b><b>)</b> 允许向项目插入一个 SQL 数据库文件。这种方法使测试数据和测试项目保持在一起。缺点是如果数据库变得很大，我们就不想这么做，而宁可提供全局的数据源。</p>
		<p>对于本项目中的数据，我们创建一个名为 <i>VSTSDemo.mdf</i><i></i>的本地项目数据库文件。为了向文件加入测试数据，我们使用菜单<b>工具</b><b>-&gt;</b><b>连接到数据库</b><b> (</b><b>Tools-&gt;Connect to Database</b><b>)</b>，然后指定 VSTSDemo.mdf 文件。然后，从服务器资源管理器窗口我们可以使用设计器加入一个新的表 <b>LongonInfoTest</b>。清单 5 显示了该表的定义。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>5. LogonInfoTestData SQL </b>
				<b>脚本</b>
		</p>
		<pre class="codeSample">CREATE TABLE dbo.LogonInfoTest
   (
   UserId nchar(256) NOT NULL PRIMARY KEY CLUSTERED,
   Password nvarchar(256) NULL,
   IsValid bit NOT NULL
   )  ON [PRIMARY]
GO
</pre>
		<p>保存表后，我们可以将其打开，然后输入不同的非法密码，如下表所示。</p>
		<table class="dataTable" id="EQNAC" cellspacing="0" cellpadding="0">
				<thead>
						<tr class="stdHeader" valign="top">
								<td id="colESNAC">UserId</td>
								<td id="colEWNAC">Password</td>
								<td id="colE1NAC" style="BORDER-RIGHT: #cccccc 1px solid">IsValid</td>
						</tr>
				</thead>
				<tbody>
						<tr class="record" valign="top">
								<td>
										<p class="lastInCell">Humperdink</p>
								</td>
								<td>
										<p class="lastInCell">P@w0d</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">False</p>
								</td>
						</tr>
						<tr class="evenRecord" valign="top">
								<td>
										<p class="lastInCell">IMontoya</p>
								</td>
								<td>
										<p class="lastInCell">p@ssword</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">False</p>
								</td>
						</tr>
						<tr class="record" valign="top">
								<td>
										<p class="lastInCell">Inigo.Montoya</p>
								</td>
								<td>
										<p class="lastInCell">P@ssw0rd</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">False</p>
								</td>
						</tr>
						<tr class="evenRecord" valign="top">
								<td>
										<p class="lastInCell">Wesley</p>
								</td>
								<td>
										<p class="lastInCell">Password</p>
								</td>
								<td style="BORDER-RIGHT: #cccccc 1px solid">
										<p class="lastInCell">False</p>
								</td>
						</tr>
				</tbody>
		</table>
		<div class="dataTableBottomMargin">
		</div>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="E2OAC">
		</a>
		<h2>将数据与测试关联</h2>
		<p>一旦完成表的创建，我们需要将其与测试 <b>InvalidPasswords()</b><b></b>联系起来。从测试 <b>InvalidPasswords</b>的属性窗口，我们填写<b>数据连接字符串</b><b></b><b>(</b><b>Data Connection String</b><b>) </b>和<b>数据表名</b><b> (</b><b>Data Table Name</b><b>) </b>属性。这样做将使用附加的属性 <b>DataSourceAttribute</b><b></b>和 <b>DataTableNameAttribute</b><b></b>更新测试。最终的方法 <b>ChangePasswordTest()</b><b></b>在清单 6 中显示。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>6. </b>
				<b>用于数据驱动测试的测试代码</b>
		</p>
		<pre class="codeSample">      
enum Column
      {
         UserId,
         Password,
         IsValid
      }

      private TestContext testContextInstance;

      /// &lt;summary&gt;
      ///Gets or sets the test context which provides
      ///information about and functionality for the 
      ///current test run.
      ///&lt;/summary&gt;
      public TestContext TestContext
      {
         get
         {
            return testContextInstance;
         }
         set
         {
            testContextInstance = value;
         }
      }

      [TestMethod]
      [Owner("Mark Michaelis")]
      [TestProperty("TestCategory", "Developer"), 
      DataSource("System.Data.SqlClient", 
         "Data Source=.\\SQLEXPRESS;AttachDbFilename=\"&lt;Path to the sample .mdf file&gt;";Integrated <br />Security=True", 
         "LogonInfoTest", 
         DataAccessMethod.Sequential)]
      public void ChangePasswordTest()
      {
         
         string userId = 
            (string)TestContext.DataRow[(int)Column.UserId];
         string password = 
            (string)TestContext.DataRow[(int)Column.Password];
         bool isValid = 
            (bool)TestContext.DataRow[(int)Column.IsValid];

         LogonInfo logonInfo = new LogonInfo(userId, "P@ssw0rd");

         if (!isValid)
         {
            Exception exception = null;
            try
            {
               logonInfo.ChangePassword(
                  "P@ssw0rd", password);
            }
            catch (Exception tempException)
            {
               exception = tempException;
            }
            Assert.IsNotNull(exception,
               "The expected exception was not thrown.");
            Assert.AreEqual&lt;Type&gt;(
               typeof(ArgumentException), exception.GetType(),
               "The exception type was unexpected.");
         }
         else
         {
            logonInfo.ChangePassword(
               "P@ssw0rd", password);
            Assert.AreEqual&lt;string&gt;(password, logonInfo.Password,
               "The password was not changed.");
         }
      }
</pre>
		<p>清单 6 第一个需要注意的地方是增加了 <b>DataSourceAttribute</b><b></b>属性，它指明了连接字符串、表名和访问顺序。在这个清单中，我们使用数据库文件名标识数据库。这样的优点是该文件和测试项目一起迁移，假设它可能会被移动到一个相对的路径。</p>
		<p>第二个注意的地方是 <b>TestContext.DataRow</b><b></b>调用。<b>TestContext</b><b></b>是在我们运行创建测试向导时由生成器提供的属性，它在运行时由测试执行引擎自动赋值，这样我们就可以在测试中访问跟测试环境关联的数据。如图 7 所示。</p>
		<div style="WIDTH: 462px">
				<img height="406" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig7.gif" width="462" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b> 7. TestContext </b>
						<b>关联</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>如图 7 所示，<b>TestContext</b><b></b>提供了 <b>TestDirectory</b><b></b>和 <b>TestName</b><b></b>数据，以及 <b>BeginTimer()</b><b></b>和<b>EndTimer()</b><b></b>方法。对 <b>ChangePasswordTest()</b><b></b>方法最有意义的是 <b>DataRow</b><b></b>属性。因为 <b>ChangePasswordTest()</b><b></b><b>方法</b>由 <b>DataSourceAttribute</b><b></b>修饰，该属性指定的表返回每个记录时，该方法都会被调用一次。这就使测试代码使用运行中的测试的数据，而且对插入 LongonInfoTest 表的每条记录重复执行测试。如果表包含四条记录，那么测试将会分别执行四次。</p>
		<p>使用这样的数据驱动测试方法，可以很容易的提供额外的测试数据，而不需要编写任何代码。一旦需要额外的测试用例，我们需要做的就是向 LongonInfoTest 表增加关联的数据。尽管我们可以创建两个独立的测试来使用单独的表分别测试有效和无效数据，这个特定的例子合并了这些测试来显示稍微复杂的数据测试实例。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EGDAE">
		</a>
		<h2>实现和重构目标方法</h2>
		<p>现在我们已经有了测试，是时候为测试编写实现了。使用 C# 重构工具，我们可以右键单击 <b>ChangePassword()</b>方法调用，选择菜单<b>项</b><b>GenerateMethodStub</b>，然后对于生成的方法提供实现，一旦我们成功地运行了使用所有测试数据的测试，我们也可以开始重构代码了，<b>LogonInfo </b>类的最终实现如清单 7 所示。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>7. LogonInfo</b>
				<b>
				</b>
				<b>类</b>
		</p>
		<pre class="codeSample">using System;
using System.Text.RegularExpressions;

namespace VSTTDemo
{
   public class LogonInfo
   {
      public LogonInfo(string userId, string password)
      {
         this.UserId = userId;
         this.Password = password;
      }

      private string _UserId;
      public string UserId
      {
         get { return _UserId; }
         private set
         {
            if (value == null || value.Trim() == string.Empty)
            {
               throw new ArgumentException(
                  "Parameter userId may not be null or blank.");
            }
            _UserId = value;
         }
      }

      private string _Password;
      public string Password
      {
         get { return _Password; }
         private set
         {
            string errorMessage;
            if (!IsValidPassword(value, out errorMessage))
            {
               throw new ArgumentException(
                  errorMessage);
            }
            _Password = value;
         }
      }

      public static bool IsValidPassword(string value, 
         out string errorMessage)
      {
         const string passwordSizeRegex = "(?=^.{6,255}$)";
         const string uppercaseRegex = "(?=.*[A-Z])";
         const string lowercaseRegex = "(?=.*[a-z])";
         const string punctuationRegex = @"(?=.*\d)";
         const string upperlowernumericRegex = "(?=.*[^A-Za-z0-9])";

         bool isValid;
         Regex regex = new Regex(
            passwordSizeRegex +
            "(" + punctuationRegex + uppercaseRegex + lowercaseRegex +
               "|" + punctuationRegex + upperlowernumericRegex + lowercaseRegex +
               "|" + upperlowernumericRegex + uppercaseRegex + lowercaseRegex +
               "|" + punctuationRegex + uppercaseRegex + upperlowernumericRegex +
            ")^.*");

         if (value == null || value.Trim() == string.Empty)
         {
            isValid = false;
            errorMessage = "Password may not be null or blank.";
         }
         else
         {
            if (regex.Match(value).Success)
            {
               isValid = true;
               errorMessage = "";
            }
            else
            {
               isValid = false;
               errorMessage = "Password does not meet the complexity requirements.";
            }
         }
         return isValid;
      }

      public void ChangePassword(
         string oldPassword, string newPassword)
      {
         if (oldPassword == Password)
         {
            Password = newPassword;
         }
         else
         {
            throw new ArgumentException(
               "The old password was not correct.");
         }
      }
   }
}
</pre>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EDEAE">
		</a>
		<h2>代码覆盖</h2>
		<p>单元测试的一个关键度量是决定在单元测试运行时测试了多少代码。该度量称为代码覆盖，Team Test 包含了一个代码覆盖工具，可以详细解释被执行代码的百分率，并突出显示哪些代码被执行，那些没有被执行。该功能如图 8 所示。</p>
		<div style="WIDTH: 459px">
				<img height="322" alt="" src="http://www.microsoft.com/china/msdn/library/langtool/vsts/art/vstsunittesting-fig8.gif" width="459" border="0" />
				<br />
				<p class="figureCaption">
						<b>图</b>
						<b>
						</b>
						<b>8. </b>
						<b>突出显示代码覆盖</b>
				</p>
				<div class="figureRule">
				</div>
		</div>
		<p>图 8 显示了运行所有单元测试后的代码覆盖的突出显示情况。红色突出显示说明了我们有产品代码没有运行任何单元测试，这说明我们编写这些代码时未遵循 TDD 原则，即在编写实现前先提供测试。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EXEAE">
		</a>
		<h2>初始化和清除测试</h2>
		<p>一般来说，测试类不仅包含独立的测试方法，还包含了不同的对测试进行初始化和清除的方法。实际上，创建测试向导在创建 VSTSDemo.Test 项目时，将一些这样的方法添加到类 <b>LongonInfoTest </b>中，见清单 8。</p>
		<p>
				<b>清单</b>
				<b>
				</b>
				<b>8. </b>
				<b>最终的</b>
				<b>
				</b>
				<b>LogonInfoTest</b>
				<b>
				</b>
				<b>类</b>
		</p>
		<pre class="codeSample">using VSTTDemo;
using Microsoft.VisualStudio.QualityTools.UnitTesting.Framework;
using System;

namespace VSTSDemo.Test
{
   /// &lt;summary&gt;
   ///This is a test class for VSTTDemo.LogonInfo and is intended
   ///to contain all VSTTDemo.LogonInfo Unit Tests
   ///&lt;/summary&gt;
   [TestClass()]
   public class LogonInfoTest
   {

      private TestContext testContextInstance;

      /// &lt;summary&gt;
      ///Gets or sets the test context which provides
      ///information about and functionality for the 
      ///current test run.
      ///&lt;/summary&gt;
      public TestContext TestContext
      {
         get
         {
            return testContextInstance;
         }
         set
         {
            testContextInstance = value;
         }
      }

      /// &lt;summary&gt;
      ///Initialize() is called once during test execution before
      ///test methods in this test class are executed.
      ///&lt;/summary&gt;
      [TestInitialize()]
      public void Initialize()
      {
         //  TODO: Add test initialization code
      }

      /// &lt;summary&gt;
      ///Cleanup() is called once during test execution after
      ///test methods in this class have executed unless
      ///this test class' Initialize() method throws an exception.
      ///&lt;/summary&gt;
      [TestCleanup()]
      public void Cleanup()
      {
         
         //  TODO: Add test cleanup code
      }


      // ...

      [TestMethod]
      // ...
      public void ChangePasswordTest()
      {   
      // ...
      }

   }
}
</pre>
		<p>用于对测试进行设置和清除的方法分别由属性 <b>TestInitializeAttribute</b><b></b>和 <b>TestCleanupAttribute</b><b></b>修饰。在每个这样的方法中，我们可以加入额外的代码，它们将会在每个测试前或者测试后运行。这意味着在每次对应于 LongonInfoTest 表的记录的 <b>ChangePasswordTest()</b><b></b>执行前，<b>Initialize() </b>和 <b>Cleanup() </b>都会被执行，每次 <b>NullUserIdInConstructor</b><b></b>和 <b>EmptyUserIdInConstructor</b><b></b>执行时也会发生同样的情况。这样的方法可以用于向数据库中插入默认的数据，然后在测试完成时清除插入的数据。例如，我们可以做到在 <b>Initialize()</b><b></b>中开始一个事务，然后在清除时回滚同一个事务，这样一来，如果测试方法使用相同的连接时，数据状态会在每次测试执行完成时恢复原状。类似地，测试文件也可以这样处理。</p>
		<p>在调试期间，<b>TestCleanupAttribute</b><b></b>修饰的方法可能由于调试器在清除的代码执行前终止运行。由于这个原因，最好在设置测试期间检查清除情况，并在需要时在设置测试前执行清除代码。关于初始化和清除的其它可用的测试属性有 <b>AssemblyInitializeAttribute/AssemblyCleanupAttribute</b><b></b>和 <b>ClassInitializeAttribute/ClassCleanupAttribute</b>。程序集相关的属性对整个程序集运行一次，而类相关的属性对一个特定的测试类的加载运行一次。</p>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EHHAE">
		</a>
		<h2>最佳实践</h2>
		<p>在结束前我们回顾几种单元测试的最佳实践。首先，TDD 是非常有价值的实践。在所有现有的开发方法中，TDD 可能是多年来根本上改进开发且投资成本最小的一种。每个 QA 工程师都会告诉您，开发人员在没有相应的测试前不会写出成功的软件。有了 TDD，实践是在实现前编写测试，并且理想情况是，编写的测试可以成为无需人工参与执行的构建脚本的一部分。需要训练来开始养成习惯，但一旦建立习惯后，不使用 TDD 方法编码就像开车时不系安全带一样。</p>
		<p>对于测试本身，有一些额外的原则可以帮助成功进行测试：</p>
		<table cellspacing="0" cellpadding="0" border="0">
				<tbody>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>避免测试产生依赖性，这样测试需要按照特定的顺序执行。每个测试都应该是自治的。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>使用测试初始化代码验证测试清除已经成功执行，如果没有则在执行测试前重新执行清除。 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>在编写任何产品代码的实现前编写测试。 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>对于产品代码中的每个类创建一个测试类。这样可以简化测试的组织，并可以容易地选择在何处放置每个测试。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>使用 Visual Studio 生成初始化的测试项目。这样可以大大减少手工设置测试项目并与产品项目关联的步骤。 </p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>避免创建其他依赖计算机的测试，例如依赖特定的目录路径的测试。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>创建模拟对象 (mock object) 来测试接口。模拟对象通常在需要验证 API 符合所需功能的测试项目中实现。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>在继续创建新的测试前验证所有测试运行成功。这样可以保证在破坏代码后立刻进行修正。</p>
								</td>
						</tr>
						<tr>
								<td class="listBullet" valign="top">•</td>
								<td class="listItem">
										<p>可以最大化无需人工参与执行的测试代码。在依赖于手工测试前，必须完全肯定无法采用合理的无需人工参与执行的测试方案。 </p>
								</td>
						</tr>
				</tbody>
		</table>
		<div style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px">
				<a href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">
						<img height="9" alt="返回页首" src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width="7" border="0" />
				</a>
				<a class="topOfPage" href="http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx#top">返回页首</a>
		</div>
		<a name="EAIAE">
		</a>
		<h2>小结</h2>
		<p>总的来说，VSTS 的单元测试功能本身很好理解。而且尽管本文没有提到，它还可以通过自定义执行引擎进行扩展。此外，它包含了代码覆盖分析的功能，这对于评价测试的全面性非常有用。通过使用 VSTS，您可以将测试数目和 bug 数目或编写的代码数量进行关联比较。这为项目的运行状况提供了很好的指标。</p>
		<p>本文介绍了Team Test 产品中的基本单元测试功能，也探讨了关于数据驱动测试的一些更加高级的功能。通过开始实践对代码进行单元测试，您会为产品的整个生命期建立一套宝贵的测试集。Team Test 通过与 Visual Studio 的强大集成和其它 VSTS 产品线，使这一切变得容易。</p>
		<p>
				<b>Mark Michaelis</b> 在 Itron 公司担任软件架构师和讲师。他曾经对几个微软的产品设计进行检查，包括 C# 和VSTS。现在他正在撰写另外一本有关 C# 的书，Essential C# (Addison Wesley)。不使用计算机时，他会陪伴家人，进行户外运动，或者进行环球旅行。Mark Michaelis 住在 Spokane, WA。您可以通过 <a href="mailto:mark@michaelis.net"><em>mark@michaelis.net</em></a> 和他联系或者访问他的网络日志：<a href="http://mark.michaelis.net/" target="_blank">http://mark.michaelis.net</a>。</p>
		<p>
				<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/vstsunittesting.asp" target="_blank">转到原英文页面</a>
		</p>
		<p>翻译者Luke是微软公司的软件工程师，习惯使用C++和C#开发应用程序。闲暇时间他喜欢音乐，旅游和怀旧游戏，并且愿意帮助MSDN翻译更多的文章和其他开发者共享。可以通过ecaijw@msn.com联系他。</p>
<img src ="http://www.cppblog.com/mzty/aggbug/8624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-06-16 11:46 <a href="http://www.cppblog.com/mzty/archive/2006/06/16/8624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Make Your Apps Fly with the New Enterprise Performance Tool (通过新的 Enterprise Performance Tool 使应用程序飞速运行)(包含各种排序算法的实现)</title><link>http://www.cppblog.com/mzty/archive/2006/04/27/6389.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Thu, 27 Apr 2006 09:46:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/04/27/6389.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/6389.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/04/27/6389.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/6389.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/6389.html</trackback:ping><description><![CDATA[
		<a href="http://msdn.microsoft.com/msdnmag/issues/04/12/EnterprisePerformance/default.aspx#contents">http://msdn.microsoft.com/msdnmag/issues/04/12/EnterprisePerformance/default.aspx#contents</a>
		<br />
		<br />
		<br />中文:http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/enterpriseperformance.mspx?mfr=true<br /><br /><br /><div class="date">发布日期： 1/6/2005<span class="datePipe"> | </span>更新日期： 1/6/2005</div><div class="overview"><p><a href="http://msdn.microsoft.com/msdnmag/find/default.aspx?type=Au&amp;phrase=John%20Robbins" target="_blank"><em>John Robbins</em></a></p><p>本文基于 Visual Studio 2005 的预发布版本。文中包含的所有信息均有可能变更。</p><p>本文讨论： </p><table cellspacing="0" cellpadding="0" border="0"><tbody><tr><td class="listBullet" valign="top">•</td><td class="listItem"><p>分析器的内部工作方式 </p></td></tr><tr><td class="listBullet" valign="top">•</td><td class="listItem"><p>EPT 的灵活功能 </p></td></tr><tr><td class="listBullet" valign="top">•</td><td class="listItem"><p>一个供分析的示例应用程序</p></td></tr></tbody></table><p><b>代码可从以下位置下载：</b><br /><a href="http://download.microsoft.com/download/d/3/1/d31fff33-fd97-488f-9bbd-4b7402905716/EnterprisePerformance.exe" target="_blank"><em>EnterprisePerformance.exe</em></a> (258KB)</p><p>快速代码仍然很受欢迎。即使我用来键入本文的计算机具有足够的能力和内存，能够同时控制一座原子能发电厂、一个火星漫游计划以及美国西部上空的空中交通，并且仍然具有充足的能力来处理星际探索中的 SETI 数据包，但这并不意味着开发人员不再需要担心其代码的速度和效率。在过去进行 Win32®<sup></sup> 本机开发的日子里，我们不仅需要担心速度，而且还要担心 PC 平台上那些令人讨厌的访问冲突（对于你们这些老家伙，还有“全局保护错误”和“不可恢复的应用程序错误”）。尽管托管代码已经消除了其中的一些担心，但它只意味着您所经历的那些性能问题可能比以前更加难以捉摸。主要原因是，在使用托管代码时，我们不具有在进行本机开发时所拥有的简便的运行库视图。</p><p>有许多次，当我正在使用客户端时，我不知道如何解决恶性的性能问题。当然，这些性能问题不会出现在任何测试系统中；它们只会出现在真实世界的生产中。由于公共语言运行库 (CLR) 是黑盒，因此如果我希望找到在测试系统中重复性能问题的方法，则很难预测会发生什么事情。尽管在市场中有一些第三方商业性能工具，但这些工具中的大多数都会对系统造成过多的干扰，以至于根本不能考虑在生产系统中使用。这也就是当我看到 Microsoft 将提供一个全新的分析器 — Enterprise Performance Tool (EPT) 以作为 Visual Studio® 2005 Team Developer Edition 的一部分时，感到如此兴奋的原因。它是我可以真正考虑在生产系统中使用的第一个分析系统，因为它提供了一些非常轻便的收集性能数据的手段。因为我曾经领导过一种最畅销的商业分析器的开发工作，所以我能够理解在不产生太多系统开销的情况下收集有用分析数据的困难程度。</p><p>在本文中，我将介绍 EPT 的基本原理，并向您说明如何开始使用它。因为分析器所具有的复杂性，所以在将来某一期中，我将讨论如何使用 EPT 来跟踪您可能在同事的代码中遇到的实际性能问题（我知道您的代码非常完美！）。请记住，EPT 正处在测试阶段（我使用的是 Burton Beta 1 刷新位版本 40607.83），并且在该产品发布之前，可能会对 UI 或某些特定步骤进行更改。在对 EPT 进行介绍之前，我希望花点儿时间谈论一下分析器通常是如何工作的，以便您可以更好地了解是什么使 Enterprise Performance Tool 变得如此与众不同。</p><p><br />分析器的基本原理</p><p>在您编写分析器时，可以选择两种收集数据的方式中的一种：探测和采样。这两种方式都十分有效，但是每种方式都有它的折衷方案。探测分析器收集数据的方式是在应用程序中插入探测或挂钩，以便在程序执行该挂钩时就调用分析器运行库。要放置探测，分析器需要在编译步骤中将应用程序仪表化，重写已经编译的二进制文件，或者即时将应用程序仪表化。要查看基于 .NET 的应用程序的探测分析器方法示例，请阅读 Aleksandr Mikunov 的一篇非常出色的文章 —“<a href="http://msdn.microsoft.com/msdnmag/issues/03/09/NETProfilingAPI" target="_blank"><em>Rewrite MSIL Code On the Fly with the .NET Framework Profiling API</em></a>”（该文章摘自 <i>MSDN</i>®<i>Magazine</i> 2003 年 9 月刊）。当我开始讨论 EPT 的时候，您将看到它使用术语“仪表化”来表示探测方法。</p><p>探测分析器方法的主要优势在于，当应用程序执行时，将始终调用所插入的探测。这样，分析器运行库将对运行具有完整的认识，因此在生成关键信息（例如，函数之间的父子关系）时可以确保正确，并且分析器可以报告完美的调用树，以便您可以轻松找到花费最长时间的调用路径。使用探测分析器时，没有什么事情能够阻止开发人员只在函数入口和出口处插入探测。可以在源代码行级别放置额外的探测，以便您对函数具有完整的认识。</p><p>但是，探测分析器所提供的详细视图具有一些缺点。第一个缺点是仪表化方案使用起来可能很麻烦，并且因为它是在二进制级别重写，因此存在很多可能引入潜在错误的领域。正如您可以想像到的那样，这些探测还占用了空间，从而导致一些代码膨胀和较低的性能。对于完全仪表化的应用程序，探测分析器可能会导致速度大幅度下降，以至于几乎不可能在生产系统上运行仪表化的二进制文件，从而使您在最需要该分析器的时候却无法利用它。</p><p>正如其名称所暗示的那样，采样分析器按照预先定义的时间间隔获得应用程序中正在执行的操作的快照。大多数开发人员都没有意识到 Microsoft 总是在他们的开发环境中随附了一个采样分析器。它被称为调试器！ 如果您开始调试应用程序，并且每隔 30 秒左右就中断至调试器，则您可以注意到应用程序线程正在何处执行，以便很好地了解应用程序在一次运行过程中执行了哪些操作。我已经通过手动完成采样分析器的工作，解决了很多生产性能问题。</p><p>使采样分析器如此有价值的原因在于，它们具有比探测分析器小得多的系统开销。这意味着，您可以有更高的机会在生产系统中使用它们，而不会使服务器疲于奔命以至于停机。采样分析器的问题在于，从应用程序中获得的所有样本很有可能根本不显示任何代码。例如，如果您具有大量使用数据库的应用程序，则所有样本都可以来自数据库访问程序集的内部。最后，只抓取每个线程的当前执行指令的传统采样分析器会使得确定方法之间的父子关系变得十分困难，因而确定性能最差的执行代码途径要困难得多。</p><p><br />Enterprise Performance Tool 的基本原理</p><p>在了解分析器的操作方式之后，我就可以讨论 EPT 所采取的方式了。简单地说：它既是采样分析器，又是探测分析器（Microsoft 称之为“仪表化”）。其思想是，您在开始时将通过采样分析器来查看应用程序性能，以获得常规性能特征，以便您可以开始将注意力集中于应用程序的热点问题上。在您了解具有一些问题的程序集之后，就可以求助于仪表化分析以查看特定的问题领域，以便修复它们。当然，如果您要执行单元性能测试，则没有什么能够阻止您直接转到对特定模块进行仪表化，以便在聚焦方案中查看它们的性能。</p><p>使 EPT 采样分析器有趣的部分原因在于，您可以使用大量项目来触发样本。默认的采样点是时钟周期，并且可能是您总是使用的采样点。默认情况下，每一百万个时钟周期采样一次，但是您可以将采样间隔的时钟周期数更改为您喜欢的任何值，可是该值越小，EPT 所导致的系统开销就越大。对于生产服务器，您可以将该数字设置为某个非常高的数字（如五百万），以使系统开销保持在合理的水平，同时不会完全破坏进程中的可用性。正如您预料的那样，每五百万个时钟周期采样一次将意味着您需要使应用程序运行相当长的时间，以便在您的热点区域中获得良好的样本分布。</p><p>如果您的应用程序使用了很多内存，则可以选择让 EPT 采样分析器改为在出现页错误时触发。这样，您就可以在数据被交换出 RAM 时获得性能快照，并且可以看到是谁在执行推送操作。如果初始分析器运行表明您在代码外部的区域中花费了大量时间，则可以告诉分析器改为基于系统调用来完成采样。如果您要分析具有大量线程的多线程应用程序，则该采样统计信息会对您在从用户模式转换到内核模式（这表明某些线程可能会不必要地在内核对象上阻塞）时的数据进行拍照。您可以用于采样触发器的最后一些值是 CPU 所支持的各种性能计数器，例如，分支计数或缓存丢失。这是一个只有极少数人才确实需要的高级选项，但是如果您确实需要该数据，那么知道该数据存在也不错。</p><p>那些忙碌的 Redmontonian 还解决了调用堆栈问题 — 这是对有用的采样分析器造成障碍的最大问题之一。正如我在前面提到的那样，大多数采样分析器在采样时只是对当前正在执行的指令进行拍照。Microsoft 解决了如何将极快的堆栈遍历结合到他们的采样分析器部分中，以便您能够获得样本的好处，并且知道在执行该样本时是如何到达那里的。这使得将这些快照与代码重新关联变得更加容易。</p><p>在讨论您可以分析的应用程序之前，我想提几件您很可能觉得有趣的事情。第一件事情是，如果您认为 Microsoft 是从头开发该性能工具的，那么您只猜对了一半。在 Microsoft 内部，开发团队一直在使用 EPT 的前身（名为 Call Attribute Profiler (CAP)，它使用仪表化）和 Low Overhead Profiler (LOP) — 一个采样分析器。由于 Microsoft 开发了这些工具以收集有关应用程序（例如，操作系统和整个 Office 套件）的性能信息，因此它们甚至不会给您的应用程序带来什么负担。我曾经使用过 EPT 的前身，所以我可以告诉您公共版本使用起来会容易多少。此外，它们还具有一些极为有趣的功能（稍后我将予以讨论）。</p><p>第二个有趣的事项与 EPT 所支持的技术有关。尽管某些人可能认为由于 Microsoft 非常偏重于 .NET Framework，因此无法将 EPT 用于 Win32 应用程序或本机代码，但 EPT 团队实际上已经承诺支持所有的 Win32 本机应用程序以及 .NET 代码。这意味着，无论您使用哪种技术（ASP.NET、Windows® 窗体、MFC 或 Win32 服务），您都具有完全的采样和仪表化支持。您将看到，在 Visual Studio .NET 中，跨技术使用 EPT 没有任何差异。</p><p>实际的 EPT 设置非常平常；只需从 Visual Studio .NET 安装程序的“Enterprise Tools”树控件中选择“Enterprise Performance Tool”即可。当然，因为您知道 EPT 仍然是一个测试产品，所以您的第一个反应可能是运行虚拟 PC，并在那里安全地包含所有内容。但是，为了执行采样分析，EPT 使用内核模式设备驱动程序来响应 CPU 性能计数器中断，不过令人遗憾的是，虚拟 PC 没有实现计数器。它也没有模拟高级可编程中断控制器 (APIC)，而这两者都是内核设备驱动程序完成其工作所必需的。好消息是，如果您没有额外的计算机以便安装 EPT，那么您也并非完全不幸，因为仪表分析器仍然能够工作。如果您没有多余的计算机以便安装 EPT，那么这是一个让公司为您购买另一台计算机的好借口。</p><p><br />Animated Algorithm</p><p>要学习任何工具的用法，您都需要一个合适的示例应用程序，以便能够最佳地利用该工具。在测试周期的这一时刻，EPT 没有随附任何示例，但是在我的硬盘上已经有了一个完美的分析器示例。早些时候，我正在尝试解决如何在 Windows 窗体应用程序中使用多线程的问题，因此我编写了一个名为 Animated Algorithm 的了不起的小程序，该程序可实时激活大量排序算法。<b>图 1</b> 显示我的示例应用程序已经准备好排序。</p><div style="WIDTH: 260px"><img height="320" alt="" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Enterprisefig01.gif" width="260" border="0" /><br /><p class="figureCaption"><b>图 1 正在工作的 Animated Algorithm</b></p><div class="figureRule"></div></div><p>Animated Algorithm 使您可以在窗体的组合框中，从 15 个不同的排序算法中进行选择。“Options”菜单使您可以选择各个元素交换或设置之间的休眠时间，以便您可以降低图形更新的速度。</p><p>我不久前使用 Microsoft® .NET Framework 版本 1.1 编写了 Animated Algorithm，因此您不会在代码中找到任何奇特的泛型或新的 BackgroundWorker 项。NSORT 程序集中的排序算法来自由 Jonathan de Halleux、Marc Clifton 和 Robert Rohde 张贴到 The Code Project 上的一篇优秀文章（请参阅 <a href="http://www.codeproject.com/csharp/cssorters.asp" target="_blank"><em>Sorting Algorithms In C#</em></a>），该程序集将算法封装到公共结构中，以便您可以轻松地替换执行元素交换和设置的类。因为它们具有非常好的体系结构，所以我需要关心的所有内容为 UI 部分。</p><p>在本文的其余部分中，我将分析 Animated Algorithm 程序。如果 EPT 团队将该程序作为示例应用程序随附在产品中，则会非常棒。（哈哈。）</p><p><br />EPT 入门</p><p>在 Visual Studio 2005 Beta 1 中，在哪里可以找到 EPT 当然是不明显的。EPT 在您启动 Performance Wizard（它位于“Tools”菜单下）时启动，并且无论是否打开项目，它都存在。请记住，Performance Wizard 所创建的性能会话不是项目的一部分；它们实际上是具有自己的 IDE 窗口（称为 Performance Explorer）的单独文件。您可以通过从“File”|“Open”对话框中选择 PSESS 文件，来打开您创建的性能会话。</p><p>如果您在单步执行 Performance Wizard 时没有打开项目，则所产生的性能会话将与您指定的二进制文件相关联。但是，在测试版中，在您指定要运行的二进制文件时，必须打开关联的项目。我只是想顺便提一下这个小小的技巧，因为当我第一次遇到该问题时，它确实让我困惑不已。</p><p>在您启动 Performance Wizard 以后，呈现在您面前的第一个屏幕要求您选择要分析的应用程序。如果您打开了一个可生成多个程序集的项目（如 Animated Algorithm），则只能从该向导中选取一个程序集。如果要进行采样，则只选取这一个程序集是很好的，因为 EPT 采样会分析加载的所有程序集（包括那些来自框架类库的程序集）。但是，如果您要对多个程序集执行仪表化分析，则 Performance Wizard 只选择这一个程序集，因此您将需要在 Performance Explorer 中所生成的性能会话中指定其他项目或程序集。稍后我将向您说明如何完成该工作。</p><p>在选择了要在性能会话中使用的程序集或项目之后，您必须选取分析方法。在 Performance Explorer 中的任何位置，您都可以在采样和仪表化之间切换，以满足自己的需要；您在该向导页中进行的选择只表示您最初希望执行的操作。在选择了分析方法之后，向导就基本完成了。对于 EPT 的最终版本，您将在 Performance Wizard 中具有用于指定附加信息的更多选项。最终版本还将使您可以直接从 Performance Explorer 中创建性能会话。</p><p><b>图 2</b> 显示了 Performance Explorer 在刚刚完成 Performance Wizard 步骤以创建 AnimatedAlgorithms 项目的仪表化运行之后的窗口。要添加另一个项目的输出二进制文件，请右键单击“Targets”文件夹，然后从上下文菜单中选择“Add Target Project”。如果要添加与该项目没有关联的特定二进制文件，请选择另一个选项 —“Add Target Binary”。如果您已经选择了“Add Target Project”，则可以在产生的对话框中从已打开的解决方案中选择其他项目。</p><div style="WIDTH: 200px"><img height="124" alt="" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Enterprisefig02.gif" width="200" border="0" /><br /><p class="figureCaption"><b>图 2 Performance Explorer</b></p><div class="figureRule"></div></div><p>如果您已经选择了仪表化运行（它由绿色启动箭头下面的下拉列表框中的文本表示），则二进制文件仪表化将在程序执行之前发生。如果您不希望针对运行仪表化某个特定的二进制文件，则请右键单击该二进制文件，并取消选中“Instrument Binary”菜单选项。</p><p>如果您已经选择了采样分析，并且希望附加到某个正在运行的项目，则单击“Attach/Detach”按钮（“Start”按钮右侧的斜向箭头）将呈现“Attach Profiler to Process”对话框。通过 EPT，您可以根据需要附加到任意多的进程，以便获得对应用程序的认识。“Attach Profiler to Process”对话框还允许您从特定的二进制文件中分离分析。在将来的某一期 <i>MSDN Magazine</i> 中，我将更详细地讨论如何附加到现有的进程（特别是为了进行 ASP.NET 性能调整）。</p><p>Performance Explorer 窗口顶部的最后一个按钮是无所不在的“Properties”按钮。在启动分析运行之前，您可能希望浏览一下性能会话属性，以设置几个关键属性。第一个属性位于“General”选项卡上，它是您希望为性能会话存储性能报告的位置。在分析项目时，默认设置是将报告存储在与解决方案相同的目录中。但更好的做法是将性能会话和它们的相应报告放置在它们自己的目录中，以便您可以更容易地存储特定的运行集。这样还可以更容易地分析之前和之后的情况，以便查看您所进行的代码更改的影响。</p><p>在“General”选项卡上，您还可以在仪表化和采样分析之间切换（这会更改在 Performance Explorer 中显示的值）。在我进行的性能调整中，我喜欢将特定的会话专用于单个类型的分析，以避免出现与报告有关的混淆。没有任何事情阻止您为所有种类的特定方案（涵盖从分析类型到单个二进制文件仪表化的所有方案）创建数以百计的不同性能会话文件。我还将提一下“General”选项卡上的最后一个项，它具有一个非常诱人的名称 —“Managed Allocation Profiling”，相信这会使您感到更加好奇。在我讨论完常规分析之后，我将返回到该项。</p><p>“Performance Session”属性页上的另一个有趣的选项卡是“Sampling”选项卡（请参见<b>图 3</b>）。在这里，您可以告诉 EPT 您要执行哪种类型的采样。正如我在前面提到的那样，您对于希望如何进行采样具有非常好的控制。</p><div style="WIDTH: 360px"><img height="288" alt="" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Enterprisefig03.gif" width="360" border="0" /><br /><p class="figureCaption"><b>图 3 各种 EPT 采样计数器选项</b></p><div class="figureRule"></div></div><p>在执行分析运行时，EPT 会在二进制文件在硬盘中所处的位置上将其仪表化。如果您希望将仪表化的二进制文件移动到另一个位置，请选择“Performance Session”属性页中的“Binary”选项卡，然后选中“Relocate Instrumented Binaries”（它与 REBASE 样式的重定位绝对没有任何关系），并且指定您希望将更改后的二进制文件移至何处。</p><p>“Instrumentation”选项卡使您可以指定希望在仪表化发生之前和之后运行的程序。如果您需要对仪表化的二进制文件执行其他任务（例如，将其移动到全局程序集缓存中或 Web 服务器上的特定位置），则该选项卡可能很有用。“Advanced”选项卡在该测试版中未公开。最后，通过“Counters”选项卡，您可以告诉 EPT 从系统的 CPU 中收集其他数据，例如，L2 或 L3 缓存读取不中。显然，这些选项是只有少数开发人员才会需要的非常高级的选项，但是如果您确实需要它们，那么它们可以发挥巨大的作用。</p><p>在我继续讨论查看采样数据之前，我想提一下，“Performance Explorer”窗口可以根据您的需要打开任意多个性能会话。当您希望观察特定的前后方案，或者希望用不同的仪表化二进制文件执行单独的测试运行时，这一点极为有用。当您打开多个性能会话时，应当确保右键单击特定的会话，选择“Set as Current Session”以便让该会话的设置执行，然后将报告归档到它的报告节点中。</p><p><br />查看分析器数据</p><p>将性能会话设置为您希望执行的操作以后，就可以启动分析了。我将首先对 Animated Algorithm 执行采样分析，以查看我是否可以找到一些热点。从采样中获得良好数据的关键在于执行较长时间的运行。对于 Animated Algorithm，我会将 15 个排序算法中的每一个算法运行两次，并将采样设置为默认的一百万个时钟周期。</p><p>在完成某个运行之后，EPT 会将该运行的报告放到性能会话的“Reports”文件夹中。EPT 在运行期间收集原始性能数据，并将其流式传输到报告文件中（不做任何分析）。这样，您可以在运行应用程序时避免所有系统开销，但是您将为大型报告文件付出代价。我刚才完成的运行的采样报告文件大小为 3.70MB，它用了大约三分钟才完成。请确保您在运行 EPT 时具有大量的磁盘空间。</p><p>所有数据分析（它必然伴有调用堆栈的生成以及性能数字的计算）都在您打开报告文件时发生。对于测试版，在打开文件时速度可能会降低。看起来视图好像处于无限循环中，但是，如果进度栏正在报告窗口中移动，那么请您耐心一些，文件最终将弹出。</p><p>任何分析运行中的第一个视图是“Performance Report Summary”，它显示在刚刚完成的 Animated Algorithm 采样运行的<b>图 4 </b>中。不出所料，采样将发生在整个应用程序中，因此您正在查看的信息也就是您将在应用程序中看到的内容：大部分工作都发生在框架类库或操作系统内部。如果您确实在采样“Summary”视图中看到了您的一个方法，则您很可能看到了一个性能问题。</p><div style="WIDTH: 340px"><img height="292" alt="" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Enterprisefig04.gif" width="340" border="0" /><br /><p class="figureCaption"><b>图 4 EPT 采样性能报告摘要</b></p><div class="figureRule"></div></div><p>快速浏览一下<b>图 4</b>，您可能想知道 Inclusive Sampled 和 Exclusive Sampled 之间的区别。Exclusive Sampled 意味着该方法在取样时位于堆栈的顶部。换句话说，它是当前正在执行的函数。Inclusive Sampled 意味着该函数在取样时出现在调用堆栈中。因而，包含方法是当前正在执行的方法的调用方。</p><p>在采样方案中，一个方法在调用堆栈 (Inclusive Sampled) 中出现的次数越多，该函数在执行中花费的时间就越多，因此这里是您需要重点关注以进行性能调整的地方。对于 Exclusive Sampled 函数而言，函数在那里频繁出现表明该函数正在被频繁地调用，但是它的执行实际上可能非常快速。对于像 Animated Algorithm 这样需要进行大量图形处理的应用程序，我完全能够预料到 GDIPLUS.DLL 中的某个函数将靠近刚刚显示的列表的顶部。在<b>图 4</b> 中，位于 GDIPLUS.DLL 中偏移量 0x5B8D 处的函数（它恰好是 FLOOR 函数）被一直调用，以便计算在屏幕上的哪个位置显示某些内容。当您观察性能运行时，请确保设置符号服务器以获得可能存在的最佳信息。在撰写本文时，我使用了 EPT 的未发布版本，因而符号尚不可用。</p><p>在我跳到其他视图中以前，我希望仪表化 Animated Algorithm，并且完成与我针对采样分析器完成的运行相同的运行，以便显示仪表化运行的性能报告摘要。正如您可以猜到的那样，仪表化的运行会生成比采样运行多得多的数据。对于该运行，我仪表化了 Animated Algorithm 中的全部五个程序集，并最终得到一个 375MB 大小的会话文件。</p><p>采样和仪表化数据之间的主要区别是：采样查看整个进程空间，并且将显示框架类库或操作系统内部（换句话说，就是您在其中不具有源代码的位置）的调用。另一方面，仪表化只查看应用程序以及您在非仪表化模块上直接调用的方法。例如，如果您具有一个“Hello World!”应用程序，并且它的 Main 只调用 Console.WriteLine，则您将获得 Main 中任何工作的计时信息以及 Console.WriteLine 长度的计时信息，但是您不会获得有关 Console.WriteLine 方法的任何详细信息。</p><p><b>图 5</b> 显示了仪表化运行的性能报告摘要。第一个表“Most Called Functions”显示了频繁使用的函数。该表中的第一列被错误标记为时间；它实际上表示对该函数的调用次数。百分比列显示了对该特定函数进行的调用总次数所占的百分比。在大多数运行中，您将在这里看到框架类库或操作系统函数。如果您看到一些来自您自己的代码的函数，则您最好了解一下您为什么如此频繁地调用该特定函数。</p><div style="WIDTH: 340px"><img height="383" alt="" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Enterprisefig05.gif" width="340" border="0" /><br /><p class="figureCaption"><b>图 5 仪表化运行的摘要</b></p><div class="figureRule"></div></div><p>“Functions with Most Individual Work”表列出了那些花费大部分时间以仅仅执行该函数（没有任何其他函数调用）的方法。这也称为该函数的独占时间。对于测试版本，“Time”列的单位为时钟走格数。对于最终版本，单位将是毫秒。但是，我认为性能运行的实际原始单位对于分析没有用。最重要的数字是百分比。在观察性能问题时，您希望知道，与应用程序中的所有其他方法相比，哪个方法占用了最长的时间。您在观察像 3519639455 和 3492589504 这样的两个数字时，很难对它们进行什么比较。幸运的是，该表包含百分比，而我对 EPT 团队的建议是从图表中丢弃原始数据。</p><p>最后一个表“Functions Taking Longest”显示方法的实际时间（也称为跑表时间或运行时间）。分析器记录方法的入口点时间和出口点时间，并将这两个值相减。该数字涵盖了被调用的所有子方法、所有上下文切换以及该方法执行的休眠。在<b>图 5</b> 中，您可以看到 System.Windows.Forms.Application.Run 占用了最长时间，就像您对 Windows 窗体应用程序所预料的那样。尽管很多开发人员将注意力集中于独占时间，但这只是整个性能状况的一小部分。如果方法正在对数据库进行调用或者进行 Web 服务调用，则您的方法在运行时所在的线程将在等待这些调用返回数据时阻塞，从而使得该线程从 CPU 中被移走。通过密切关注方法的运行时间，您可以找到代码中正在降低应用程序运行速度的部分。</p><p>尽管摘要视图很不错，但您最感兴趣的将是查看代码在何处阻塞了系统的其余部分（对于采样运行而言），或者阻塞了应用程序的其他方法（对于仪表化运行而言）。这是“Function”视图的职责范围 — 通过单击报告窗口底部的“Function”按钮可以选择该视图。您还可以双击“Summary”视图的任何方法以跳至“Function”视图。</p><p>对于采样运行，“Function”视图显示了至少一个包含捕获中所有函数捕获的列表。对于仪表化运行，您将看到作为该运行的一部分调用的所有仪表化方法。无论您正在执行哪种类型的分析，都会在“Function”视图中显示很多数据，因此您可以对代码的状况有一点儿感觉。</p><p>默认情况下，采样“Function”视图显示“Inclusive Samples”列和“Exclusive Samples”列。由于我喜欢百分比数字，因此我右键单击了列标题以向列标题中添加“Inclusive Percent”和“Exclusive Percent”。如果您要对多进程系统进行采样，则可能希望包含其他列（例如，“Process Name”或“Process ID”），以便您可以标识哪个方法采样与哪个进程相配。您还可以在仪表化“Function”视图中设置列标题，但是您将具有不同的标题组以供选择。</p><p>在“Function”视图中分析采样运行时，我喜欢首先扫一眼“Function”视图的头几个按“Inclusive Samples”列排序的页，以了解正在执行的方法。如果我在头几个页中没有看到我的任何方法，则我会右键单击“Function”视图并选择“Group by Module”，以便获得树报告视图。当您将函数按模块分组时，按特定列排序可以正确执行 — 这是一项很不错的功能。</p><p>对于仪表化运行，“Function”视图具有更多要显示的列。如果您拥有一台 40 英寸的显示器，则无需最大化 Visual Studio .NET 窗口就应当能够看到所有这些列。对于我们中的其他人而言，查看“Function”视图的最佳方式是按 Alt + Shift + Enter 以切换到全屏幕模式。</p><p>在这些列中，“Function”视图中的仪表化运行使用我在前面解释过的“包含”和“独占”术语。但是，还有另一个使人混淆的术语：应用程序。正如我提到的那样，运行时间是从一个仪表化点到另一个仪表化点的总时间，而不管该线程可能进行了哪些上下文切换。应用程序时间的思想是 EPT 将提取出在这些上下文切换中所花费的时间，以便您可以看到您的代码在 CPU 中实际执行的时间<b>。</b><a href="http://msdn.microsoft.com/msdnmag/issues/04/12/enterpriseperformance/default.aspx?fig=true#fig6" target="_blank"><em>图 6</em></a> 列出了您将在仪表化“Function”视图中看到的不那么明显的列的定义。您可能希望将它传送到显示器上，直到 EPT 的联机帮助问世。</p><p>在观察仪表化运行的“Function”视图时，我添加了这些列以查看各种计时的百分比值，移除原始数字时间列，并且添加了两个转换列。这为我提供了有关该运行的更清晰视图。我在排序时所依据的第一个列是“% Application Exclusive Time”，因为我希望看到哪个函数正在完成大部分工作。由于仪表化在方法进行的所有子调用周围放入了探测，所以您完全有可能在该列表的顶部看到框架类库或操作系统。实际上，对于我的 Animated Algorithm 运行，System.Drawing.SolidBrush.ctor 和 System.Drawing.Brush.Dispose 在 Application Exclusive Time 百分比中被列为第一和第二，其百分比分别为 14.982% 和 14.867%。我编写的第一个函数是位于第三位的 Bugslayer.SortDisplayGraph.SorterGraph.UpdateSingleFixedElement（其百分比为 12.217%），它在图形中绘制单独的条。根据应用程序类型的不同，我在查看“Function”视图时可能会选择按其他列排序。如果存在 Web 服务或数据库调用，则我将查看 % Elapsed Inclusive Time，以便可以看到是否有特定方法卷入到长时间阻塞中。对于像 Animated Algorithm 这样的应用程序，我还将查看 Application Inclusive Time 的百分比。</p><p>基于我的仪表化运行中的上述数字，我很想查明是谁在对 SolidBrush 方法进行这些调用，因此我右键单击 .ctor 方法并选择“Show in Caller/Callee”视图，以便查看是谁在调用该方法。该视图（它对于采样分析也可用）使您一眼就可以看出目标方法的所有调用方，以及该目标方法调用的所有方法。</p><p>因为 .ctor 方法没有仪表化，所以“Caller/Callee”视图将不会显示任何被调用方，但是它显然会显示调用方。我双击了这个唯一的调用方，它恰好是具有第三高 Application Exclusive Time 并具有<a href="http://msdn.microsoft.com/msdnmag/issues/04/12/enterpriseperformance/default.aspx?fig=true#fig7" target="_blank"><em>图 7</em></a> 所示视图的 UpdateSingleFixedElement 方法。</p><p>在<a href="http://msdn.microsoft.com/msdnmag/issues/04/12/enterpriseperformance/default.aspx?fig=true#fig7" target="_blank"><em>图 7</em></a> 中，位于视图中部的下拉组合框是目标方法（在本例中为 UpdateSingleFixedElement）。方法上方的网格包含了目标方法的所有调用方（调用方）。目标方法下方的网格包含了目标方法调用以完成其工作的所有方法（被调用方）。如果您希望查看是谁调用了特定调用方，请双击该调用方方法，该方法将变为目标方法，并且您将看到原始目标方法下降到被调用方部分中。实质上，您只是将堆栈遍历了一遍。</p><p>仅仅基于<a href="http://msdn.microsoft.com/msdnmag/issues/04/12/enterpriseperformance/default.aspx?fig=true#fig7" target="_blank"><em>图 7</em></a> 中的视图，您就可以辨别出潜在的性能问题。Animated Algorithm 似乎不具有任何突出的性能问题，但是 SolidBrush .ctor 和 Dispose 占用了如此多的时间并且都在 UpdateSingleFixedElement 方法内部调用（调用了 351,872 次），这个事实表明我做了一件愚蠢的事情 — 我每次都通过该函数创建画笔，而实际上应该将其缓存。当我在将来的某一期 <i>MSDN Magazine</i> 中开始用 EPT 分析代码时，您还将看到 Animated Algorithm 的其他一些问题。</p><p>数据的最后一个常用视图是“Callstack”视图。在这里，您可以通过更具层次性的方式看到您在“Caller/Callee”窗口中观察到的调用堆栈。对于采样运行，您将在“Callstack”视图的顶层看到很多的条目，因为这些条目中的每一个都代表一个包含独占样本的唯一点。当您在采样运行中展开项时，您还将看到，在相同级别偶尔会存在一些项，这些项指示位于根部的函数具有多个引向它的调用树。根位置中显示的项是栈顶。</p><p>对于仪表化运行，“Callstack”窗口将具有与应用程序中的每个线程相对应的根元素。因为 Animated Algorithm 只有两个线程，所以您只能在树根级别看到两个项。在“Callstack”视图中，您可以看到绝对调用堆栈（从仪表化的第一个方法向下到最后一个方法），因此您可以真正了解应用程序的执行方式。我已经有很多次对我认为代码所完成的工作和代码实际上完成的工作之间的差异感到吃惊。</p><p>您可以花费大量时间在“Callstack”窗口中分析代码。当通过应用程序观察特定的踪迹时，您可以通过选择感兴趣的特定节点，向下移动，右键单击，并选择“Set Root”菜单选项，来消除大量噪音。在<a href="http://msdn.microsoft.com/msdnmag/issues/04/12/enterpriseperformance/default.aspx?fig=true#fig8" target="_blank"><em>图 8</em></a> 中，我希望查看 NSort.SwapSorter.Sort 进行的所有调用，因此将它设置为根可以消除 UI 线程的影响。</p><p>在将来的某一期中，我将更详细地讨论 EPT 显示区域中的最后两个选项卡：“Trace”和“Type”。在“Type”视图中，您可以观察已经在应用程序中分配的对象。它在测试版中有效。当我在前面讨论性能会话属性时，我提到过在“General”选项卡上有一个“Managed Allocation Profiling”部分。如果您选择“Allocations-only”单选按钮，则 EPT 会填充“Type”视图。在测试版中，报告看起来类似于其他许多工具中的报告，但是数据收集似乎不像在其他工具中那样具有如此之多的系统开销。最后，要了解 Enterprise Performance Tool 团队的想法以及有关该工具的更多信息，请确保在 <a href="http://blogs.msdn.com/profiler" target="_blank"><em>blogs.msdn.com/profiler</em></a> 查看他们的网络日记。</p><p><b>John Robbins</b> 是 Wintellect 的创始人之一，该公司是一家专门致力于 Windows 和 .NET Framework 的软件咨询、教育和开发公司。他的最新著作是“Debugging Applications for Microsoft .NET and Microsoft Windows”(Microsoft Press, 2003)。要联系 John，请访问 <a href="http://www.wintellect.com/" target="_blank"><em>www.wintellect.com</em></a>。</p></div><img src ="http://www.cppblog.com/mzty/aggbug/6389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-04-27 17:46 <a href="http://www.cppblog.com/mzty/archive/2006/04/27/6389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs.net 2005 的test</title><link>http://www.cppblog.com/mzty/archive/2006/04/26/6332.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 26 Apr 2006 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/04/26/6332.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/6332.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/04/26/6332.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/6332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/6332.html</trackback:ping><description><![CDATA[
		<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/vstsunittesting.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/vstsunittesting.asp</a>
<img src ="http://www.cppblog.com/mzty/aggbug/6332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-04-26 17:15 <a href="http://www.cppblog.com/mzty/archive/2006/04/26/6332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>NUnit单元测试</title><link>http://www.cppblog.com/mzty/archive/2006/04/26/6309.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 26 Apr 2006 06:00:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/04/26/6309.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/6309.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/04/26/6309.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/6309.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/6309.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一 NUnit是一款堪与JUnit齐名的开源的回归测试框架，供.net开发人员做单元测试之用，可以从						www.nunit.org				网站上免费获得,我下的是 win .net 2.0NUnit-2.2.8-net-2.0.msi..二 安装NUnit(很简单的,直接next就可以拉)三 新建console的c#的.net2005的project.里面包含要被测试的...&nbsp;&nbsp;<a href='http://www.cppblog.com/mzty/archive/2006/04/26/6309.html'>阅读全文</a><img src ="http://www.cppblog.com/mzty/aggbug/6309.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-04-26 14:00 <a href="http://www.cppblog.com/mzty/archive/2006/04/26/6309.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vs.net常用快捷键 </title><link>http://www.cppblog.com/mzty/archive/2006/04/26/6306.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 26 Apr 2006 04:55:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/04/26/6306.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/6306.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/04/26/6306.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/6306.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/6306.html</trackback:ping><description><![CDATA[默认设置”快捷键<br />下表列出了可用于“默认设置”键盘方案的默认组合键。 <br /><br />“全局”快捷键<br />下列快捷组合键可用于集成开发环境 (IDE) 中的不同位置。<br /><br />命令名 快捷键 说明 <br />编辑.复制 CTRL + C<br />CTRL + INSERT 将当前选定的项复制到系统剪贴板。 <br />编辑.剪切 CTRL + X<br />SHIFT + DELETE 将当前选定的项移除到系统剪贴板。 <br />编辑.循环应用剪贴板中的复制项 CTRL + SHIFT + INS<br />CTRL + SHIFT + V 将项从“工具箱”的“剪贴板循环”选项卡粘贴在文件中的插入点，并自动选择粘贴的项。可通过重复按这些快捷键来查看剪贴板上的每个项。 <br />编辑.转到下一个位置 F8 将光标移动到下一项，如“任务列表”窗口中的任务或“查找结果”窗口中的搜索匹配项。<font color="#ff1493">每按一次 F8 键，就移动到列表中的下一个项</font>。 <br />编辑.<font color="#ff1493">转到上一个位置 SHIFT + F8 在“任务列表”窗口或“查找结果”窗口中，将光标移动到上一项。</font> <br />编辑.<font color="#ff1493">转到引用 SHIFT + F12 显示代码中所选内容的引用。</font> <br />编辑.打开文件 CTRL + SHIFT + G 显示“打开文件”对话框，在此可选择要打开的现有文件。 <br />编辑.粘贴 CTRL + V<br />SHIFT + INSERT 在插入点插入剪贴板的内容。 <br />编辑.重复 CTRL + SHIFT + Z<br />CTRL + Y<br />SHIFT + ALT + BACKSPACE 还原上次撤消的操作。 <br />编辑.取消选定 ESC 关闭菜单或对话框，取消正在进行的操作，或将焦点放在当前文档窗口中。仅在 .NET Framework 设计器中可用。 <br />编辑.撤消 ALT + BACKSPACE<br />CTRL + Z 撤消上一编辑操作。 <br />文件.打印 CTRL + P 显示“打印”对话框，可在其中选择打印机设置。 <br />文件.全部保存 CTRL + SHIFT + S 保存当前解决方案中的所有文档和外部文件项目中的任何文件。 <br />文件.保存选定项 CTRL + S 保存当前项目中的选定项。 <br />工具.转到命令行 CTRL + / 将插入符号放置在“标准”工具栏上的“查找/命令”框中。 <br />视图.下一任务 CTRL + SHIFT + F12 移到“任务列表”窗口中的下一个任务。 <br />视图.弹出浏览上下文 CTRL + SHIFT + 8 返回到上次执行浏览操作的位置。在“对象浏览器”或“类视图”窗口中可用。 <br />视图.查看代码 F7 在编辑器的“代码”视图中显示选定项。 <br />视图.视图设计器 SHIFT + F7 在编辑器的“设计”视图中显示选定项。 <br />视图.Web向后定位 ALT + 左箭头键 显示查看历史记录中的前一页。仅在“Web 浏览器”窗口中可用。 <br />视图.Web向前定位 ALT + 右箭头键 显示查看历史记录中的下一页。仅在“Web 浏览器”窗口中可用。 <br /><br />“HTML 设计器”快捷键<br />只有在 HTML 设计器中进行编辑时才能使用下列快捷组合键。某些组合键仅在该设计器的特定视图中可用。<br /><br />命令名 快捷键 说明 <br />编辑.列出成员 CTRL + J 编辑代码时，列出当前类的成员以完成语句。仅可用于 HTML 设计器的“HTML”视图。 <br />编辑.参数信息 CTRL + SHIFT + 空格键 基于当前语言显示包含当前参数信息的工具提示。仅可用于 HTML 编辑器的“HTML”视图。 <br />编辑.视图底部 CTRL + PAGE DOWN 移动到当前文档末尾。仅可用于 HTML 设计器的“HTML”视图中可用。 <br />编辑.视图顶部 CTRL + PAGE UP（将文件另存为） 移动到当前窗口的顶部。仅可用于 HTML 设计器的“HTML”视图中可用。 <br />格式.粗体 CTRL + B 在粗体和正常之间切换选定文本。仅可用于 HTML 设计器的“设计”视图。 <br />格式.书签 CTRL + SHIFT + L 显示“书签”对话框。仅可用于 HTML 设计器的“设计”视图。 <br />格式.转换为超级链接 CTRL + L 选定文本后，显示“超级链接”对话框。仅可用于 HTML 设计器的“设计”视图。 <br />格式.减少缩进 CTRL + SHIFT + T 将选定段落减少一个缩进单元。仅可用于 HTML 设计器的“设计”视图。 <br />格式.增加缩进 CTRL + T 将选定段落缩进一个缩进单元。仅可用于 HTML 设计器的“设计”视图。 <br />格式.斜体 CTRL + I 在斜体和正常之间切换选定文本。仅可用于 HTML 设计器的“设计”视图。 <br />格式.锁定元素 CTRL + SHIFT + K 防止绝对定位的元素被意外移动。仅可用于 HTML 设计器的“设计”视图。 <br />格式.显示网格 CTRL + G 切换显示网格。仅可用于 HTML 设计器的“设计”视图。 <br />格式.网格线对齐 CTRL + SHIFT + G 指定使用不可见网格对齐元素。可以在“选项”对话框中“HTML 设计器”选项的“设计”窗格上设置网格间距，网格将在您下次打开文档时更改。仅可用于 HTML 设计器的“设计”视图。 <br />格式.下划线 CTRL + U 在下划线和正常之间切换选定文本。仅可用于 HTML 设计器的“设计”视图。 <br />表.在其左侧插入列 CTRL + ALT + 左箭头键 将一列添加到表中当前列的左边。仅可用于 HTML 设计器的“设计”视图。 <br />表.在其右侧插入列 CTRL + ALT + 右箭头键 将一列添加到表中当前列的右边。仅可用于 HTML 设计器的“设计”视图。 <br />表.在其上方插入行 CTRL + ALT + 上箭头键 在表中的当前行之上添加一行。仅可用于 HTML 设计器的“设计”视图。 <br />表.在其下方插入行 CTRL + ALT + 下箭头键 在表中的当前行之下添加一行。仅可用于 HTML 设计器的“设计”视图。 <br />视图.详细信息 CTRL + SHIFT + Q 显示不具有可视化表示形式的 HTML 元素的信号图标，如绝对定位元素的注释、脚本和定位点。仅可用于 HTML 设计器的“设计”视图。 <br />视图.下一个视图 CTRL + PAGE DOWN 从“设计”视图切换到“HTML”视图，反之亦然。仅可用于 HTML 设计器的“设计”视图。 <br />视图.可视边框 CTRL + Q 在支持 BORDER 属性的 HTML 元素（如表、表单元格和间隔）周围显示 1 像素的边框并将该属性设置为零。仅可用于 HTML 设计器的“设计”视图。 <br /><br />“XML 设计器”快捷键<br />命令名 快捷键 说明 <br />架构.折叠 CTRL + (-) 折叠嵌套元素。仅用于 XML 设计器的“架构”视图。 <br />架构.展开 CTRL + (=) 展开嵌套元素。仅用于 XML 设计器的“架构”视图。 <br /><br />“控件操作”快捷键<br />下列快捷组合键可用于在设计图面上移动和选择控件以及更改控件的大小。<br /><br />命令名 快捷键 说明 <br />编辑.下移控件 CTRL + 下箭头键 在设计图面上，将选定的控件以 1 为增量向下移动。 <br />编辑.将控件移动到下侧网格 下箭头键 在设计图面上，将选定的控件以 8 为增量向下移动。 <br />编辑.左移控件 CTRL + 左箭头键 在设计图面上，将控件以 1 为增量向左移动。 <br />编辑.将控件移动到左侧网格 左箭头键 在设计图面上，将控件以 8 为增量向左移动。 <br />编辑.右移控件 CTRL + 右箭头键 在设计图面上，将控件以 1 为增量向右移动。 <br />编辑.将控件移动到右侧网格 右箭头键 在设计图面上，将控件以 8 为增量向右移动。 <br />编辑.上移控件 CTRL + 上箭头键 在设计图面上，将控件以 1 为增量向上移动。 <br />编辑.将控件移动到上侧网格 上箭头键 在设计图面上，将控件以 8 为增量向上移动。 <br />编辑.选择下一个控件 TAB 键 移动到页上的下一控件处。 <br />编辑.选择上一个控件 SHIFT + TAB 键 移回到页上上次选定的控件处。 <br />编辑.向下调整控件大小 CTRL + SHIFT + 下箭头键 在设计图面上，以 1 为增量，增加控件的高度。 <br />编辑.将控件调大到下侧网格 SHIFT + 下箭头键 在设计图面上，以 8 为增量，增加控件的高度。 <br />编辑.向左调整控件大小 CTRL + SHIFT + 左箭头键 在设计图面上，以 1 为增量，减少控件的宽度。 <br />编辑.将控件调大到左侧网格 SHIFT + 左箭头键 在设计图面上，以 8 为增量，减少控件的宽度。 <br />编辑.向右调整控件大小 CTRL + SHIFT + 右箭头键 在设计图面上，以 1 为增量，增加控件的宽度。 <br />编辑.将控件调大到右侧网格 SHIFT + 左箭头键 在设计图面上，以 8 为增量，增加控件的宽度。 <br />编辑.向上调整控件大小 CTRL + SHIFT + 上箭头键 在设计图面上，以 1 为增量，减少控件的高度。 <br />编辑.将控件调大到上侧网格 SHIFT + 上箭头键 在设计图面上，以 8 为增量，减少控件的高度。 <br /><br />“调试”快捷键<br />下列快捷组合键可在调试代码时使用。<br /><br /><font color="#ff1493">命令名 快捷键 说明 <br />调试.应用代码更改 ALT + F10 开始一个“编辑”或“继续”生成，以应用对正在调试的代码所作的更改。 <br />调试.自动窗口 CTRL + ALT + V，A 显示“自动”窗口，以查看当前过程内当前执行行范围中的当前变量的值。  <br />调试.全部中断 CTRL + ALT+ Break 临时停止执行调试会话中的所有进程。仅适用于“运行”模式。 <br />调试.断点 CTRL + ALT + B 显示“断点”对话框，在此可添加和修改断点。 <br />调试.调用堆栈 CTRL + ALT + C 显示“调用堆栈”窗口，以显示当前执行线程的所有活动过程或堆栈帧列表。仅适用于“运行”模式。 <br />调试.清除所有断点 CTRL + SHIFT + F9 清除项目中的所有断点。 <br />调试.反汇编 CTRL + ALT + D 显示“反汇编”窗口。 <br />调试.启用断点 CTRL + F9 在当前代码行设置断点。 <br />调试.异常 CTRL + ALT + E 显示“异常”对话框。 <br />调试.即时 CTRL + ALT + I 显示“即时”窗口，在此可计算表达式和执行个别命令。 <br />调试.局部变量 CTRL + ALT + V，L 显示“局部变量”窗口，以查看当前堆栈帧中每个过程的变量及其值。 <br />调试.内存1 CTRL + ALT + M，1 键 显示“内存 1”窗口，以查看在“监视”或“变量”窗口中不能清楚显示的大缓存区、字符串和其他数据。 <br />调试.内存2 CTRL + ALT + M，2 键 显示“内存 2”窗口，查看在“监视”或“变量”窗口中不能清楚地显示的大缓冲区、字符串和其他数据。 <br />调试.内存3 CTRL + ALT + M，3 键 显示“内存 3”窗口，查看在“监视”或“变量”窗口中不能清楚地显示的大缓冲区、字符串和其他数据。 <br />调试.内存4 CTRL + ALT + M，4 键 显示“内存 4”窗口，查看在“监视”或“变量”窗口中不能清楚地显示的大缓冲区、字符串和其他数据。 <br />调试.模块 CTRL + ALT + U 显示“模块”窗口，该窗口允许查看由程序使用的 .dll 或 .exe 文件。在多处理调试中，可以右击并选择“显示所有程序的模块”。 <br />调试.新断点 CTRL + B 在当前代码行中插入或清除断点。 <br />调试.快速监视 CTRL + ALT + Q 显示带有选定表达式的当前值的“快速监视”对话框。仅适用于“中断”模式。使用该命令可检查尚未为其定义监视表达式的变量、属性或其他表达式的当前值。  <br />调试.寄存器 CTRL + ALT + G 显示“寄存器”窗口，该窗口显示用于调试本机代码应用程序的寄存器内容。 <br />调试.重新启动 CTRL + SHIFT + F5 终止调试会话，重新生成，然后从开始处开始运行应用程序。可用于“中断”模式和“运行”模式。 <br />调试.运行文档 CTRL + ALT + N 显示“运行文档”窗口，该窗口显示正处于调试过程中的文档集。适用于“运行”模式。 <br />调试.运行到光标处 CTRL + F10 在“中断”模式下，从当前语句继续执行代码，直到选定语句。“当前执行行”边距指示器出现在“页边距指示符”栏中。<br />在“设计”模式下，启动调试器并执行代码，直到光标位置。 <br />调试.设置下一语句 CTRL + SHIFT + F10 在选择的代码行上设置执行点。  <br />调试.显示下一语句 ALT + 数字键区中的 * 突出显示要执行的下一条语句。 <br />调试.启动 F5 自动附加调式器，并从“&lt;Project&gt; 属性”对话框中指定的启动项目中运行应用程序。如果为“中断”模式，则更改为“继续”。 <br />调试.开始执行不调试 CTRL + F5 在不调用调试器的情况下运行代码。 <br />调试.逐语句 F11 在执行进入函数调用后，逐条语句执行代码。 <br />调试.跳出 SHIFT + F11 执行当前执行点所处函数的剩余行。 <br />调试.逐过程 F10 执行下一行代码，但不执行任何函数调用。 <br />调试.停止调试 SHIFT + F5 停止运行程序中的当前应用程序。可用于“中断”模式和“运行”模式。 <br />调试.This CTRL + ALT + V，T 显示“This”窗口，该窗口允许查看与当前方法关联的对象的数据成员。 <br />调试.线程 CTRL + ALT + H 显示“线程”窗口，查看用于当前进程的所有线程及其信息。 <br />调试.切换断点 F9 在当前行设置或移除断点。 <br />调试.切换反汇编 CTRL + F11 显示当前源文件的反汇编信息。仅适用于“中断”模式。  <br />调试.监视1 CTRL + ALT + W，1 键 显示“Watch1”窗口，以查看所选变量或监视表达式的值。 <br />调试.监视2 CTRL + ALT + W，2 键 显示“Watch2”窗口，以查看所选变量或监视表达式的值。 <br />调试.监视3 CTRL + ALT + W，3 键 显示“Watch3”窗口，以查看所选变量或监视表达式的值。 <br />调试.监视4 CTRL + ALT + W，4 键 显示“Watch4”窗口，以查看所选变量或监视表达式的值。 <br />工具.调试进程 CTRL + ALT + P 显示“进程”对话框，该对话框允许在单个解决方案中同时调试多个程序。 <br /></font><br />“搜索和替换”快捷键<br />下列快捷组合键可用于“查找”、“替换”、“在文件中查找”和“在文件中替换”对话框。<br /><br />命令名 快捷键 说明 <br /><font color="#7fffd4"><font color="#ee82ee">编辑.查找 CTRL + F 显示“查找”对话框。</font> <br /></font>编辑.在文件中查找 CTRL + SHIFT + F 显示“在文件中查找”对话框。 <br />编辑.查找下一个 F3 查找上次搜索文本的下一个匹配项。 <br />编辑.查找下一个选定项 CTRL + F3 在文档中查找当前选定文本的下一个匹配项。 <br />编辑.查找上一个 SHIFT + F3 查找搜索文本的上一个匹配项。 <br />编辑.查找上一个选定项 CTRL + SHIFT + F3 查找当前选定文本的上一匹配项或者插入符号处的单词。 <br />编辑.转到查找组合框 CTRL + D 将插入符号放置在“标准”工具栏上的“查找/命令”行中。 <br />编辑.隐藏文本 ALT + F3，H 选择或清除“查找”对话框的“搜索隐藏文本”选项。 <br />编辑.渐进式搜索 CTRL + I 启动渐进式搜索。如果启动了渐进式搜索，但尚未键入任何字符，请恢复上一模式。如果已找到文本，则搜索下一匹配项。 <br />编辑.大小写匹配 ALT + F3，C。 选择或清除“查找”和“替换”操作的“大小写匹配”选项。 <br />编辑.正则表达式 ALT + F3，R 选择或清除“正则表达式”选项，以便特殊字符可用于“查找”和“替换”操作。 <br />编辑.替换 CTRL + H 显示“替换”对话框。 <br />编辑.在文件中替换 CTRL + SHIFT + H 显示“在文件中替换”对话框。 <br />编辑.反向渐进式搜索 CTRL + SHIFT + I 更改渐进式搜索的方向，从文件尾开始向文件头搜索。 <br />编辑.停止搜索 ALT + F3，S 暂停当前的“在文件中查找”操作。 <br />编辑.向上 ALT + F3，B 选择或清除“查找”和“替换”操作的“向上搜索”选项。 <br />编辑.全字匹配 ALT + F3，W 选择或清除“查找”和“替换”操作的“全字匹配”选项。 <br />编辑.通配符 ALT + F3，P 选择或清除“查找”和“替换”操作的“通配符”选项。 <br /><br />“可视化数据库工具”快捷键<br />下列快捷组合键可用于数据库设计器或查询设计器。<br /><br />命令名 快捷键 说明 <br />数据库.运行 CTRL + E 运行当前活动的数据库对象。 <br />数据库.运行选定内容 CTRL + Q 运行 SQL 编辑器中的当前选择。 <br />数据库.逐语句 ALT + F5 使当前的活动数据库对象按步骤进入调试模式。 <br />查询.运行 CTRL + R 执行查询。仅在“查询设计器”中可用。 <br />视图.关系图 CTRL +1 键 显示“查询”设计器的“关系图”窗格。仅在“查询”设计器中可用。 <br />视图.网格 CTRL + 2 键 显示“查询”设计器的“网格”窗格。仅在“查询”设计器中可用。 <br />视图.结果 CTRL +4 键 显示“查询”设计器的“结果”窗格。仅在“查询”设计器中可用。 <br />视图.SQL CTRL +3 键 显示“查询”设计器的“SQL”窗格。仅在“查询”设计器中可用。 <br /><br /><font color="#008000">“文本导航”快捷键<br />下列快捷组合键可在文本编辑器中用于在打开的文档内进行移动。<br />命令名 快捷键 说明 <br />编辑.左移字符 左箭头键 将光标向左移动一个字符。仅在 .NET Framework 设计器中可用。 <br />编辑.右移字符 右箭头键 将光标向右移动一个字符。仅在 .NET Framework 设计器中可用 <br />编辑.文档结尾 CTRL + END 将插入点移动到文档的最后一行。 <br />编辑.文档开始 CTRL + HOME 将插入点移动到文档首行。 <br />编辑.转到 CTRL + G 显示“转到行”对话框。 <br />编辑.转到大括号 CTRL + ] 将插入点移动到文档中的下一个大括号处。 <br />编辑.向下移动一行 下箭头键 将光标下移一行。 <br />编辑.行尾 END 将光标移至当前行的结尾。 <br />编辑.行首 HOME 将光标移至当前行的开头。 <br />编辑.向上移动一行 上箭头键 将光标上移一行。 <br />编辑.下一书签 CTRL + K，CTRL + N 移动到文档中下一个书签处。 <br />编辑.向下翻页 PAGE DOWN 在编辑器窗口中向下滚动一屏。 <br />编辑.向上翻页 PAGE UP 在编辑器窗口中向上滚动一屏。 <br />编辑.上一书签 CTRL + K，CTRL + P 移动到上一书签。 <br />编辑.快速信息 CTRL + K，CTRL + I 基于当前语言显示“快速信息”。 <br />编辑.向下滚动一行 CTRL + 下箭头键 将文本向下滚动一行。仅在文本编辑器中可用。 <br />编辑.向上滚动一行 CTRL + 上箭头键 将文本向上滚动一行。仅在文本编辑器中可用。 <br />编辑.下一字 CTRL + 右箭头键 将插入点向右移动一个单词。 <br />编辑.上一字 CTRL + 左箭头键 将插入点向左移动一个单词。 <br />视图.浏览下一个 CTRL + SHIFT + 1 定位到项的下一个定义、声明或引用。在“对象浏览器”和“类视图”窗口中可用。 <br />视图.浏览上一个 CTRL + SHIFT + 2 定位到项的上一个定义、声明或引用。在“对象浏览器”和“类视图”窗口中可用。 <br /></font><br /><font color="#ff0000">“文本选择”快捷键<br />下列快捷组合键可在文本编辑器中用于在打开的文档中选择文本。<br /><br />命令名 快捷键 说明 <br />编辑.向左扩展一个字符 SHIFT + 左箭头键 将光标左移一个字符以扩展所选内容。仅在 .NET Framework 设计器中可用。 <br />编辑.向左扩展一个字符列 SHIFT + ALT + 左箭头键 将光标左移一个字符以扩展列选择。 <br />编辑.向右扩展一个字符 SHIFT + 右箭头键 将光标右移一个字符以扩展所选内容。仅在 .NET Framework 设计器中可用。 <br />编辑.向右扩展一个字符列 SHIFT + ALT + 右箭头键 将光标右移一个字符以扩展列选择。 <br />编辑.文档结尾扩展 CTRL + SHIFT + END 选择从插入点到文档最后一行的文本。 <br />编辑.文档开始扩展 CTRL + SHIFT + HOME 选择从插入点到文档首行的文本。 <br />编辑.扩展转到大括号 CTRL + SHIFT + ] 将插入点移动到下一个大括号处以扩展选定内容。 <br />编辑.向下扩展一行 SHIFT + 下箭头键 从插入点位置开始，将选定文本向下扩展一行。 <br />编辑.向下扩展列 SHIFT + ALT + 下箭头键 将光标下移一行以扩展列的选定内容。 <br />编辑.扩展到行尾 SHIFT + END 选择从插入点到当前行行尾的文本。 <br />编辑.行尾扩展列 SHIFT + ALT + END 将插入点移动到行尾以扩展列的选定内容。 <br />编辑.扩展到行首 SHIFT + HOME 选择从插入点到行首的文本。 <br />编辑.行首扩展列 SHIFT + ALT + HOME 将插入点移到行首以扩展列选择。 <br />编辑.向上扩展一行 SHIFT + 上箭头键 从插入点位置开始向上逐行选择文本。 <br />编辑.向上扩展列 SHIFT + ALT + 上箭头键 将光标上移一行以扩展列的选定内容。 <br />编辑.向下扩展一页 SHIFT + PAGE DOWN 将选定内容向下扩展一页。 <br />编辑.向上扩展一页 SHIFT + PAGE UP 将选定内容向上扩展一页。 <br />编辑.全选 CTRL + A 选择当前文档中的所有内容。 <br />编辑.选择当前字 CTRL + W 选择包含插入点的单词，或插入点右侧的单词。 <br />编辑.选择到最后一个返回 CTRL + = 选择编辑器中当前位置到编辑器中前一位置之间的内容。 <br />编辑.扩展到视图底部 CTRL + SHIFT + PAGE DOWN 将光标移动到视图中的最后一行以扩展选定内容。 <br />编辑.扩展到视图顶部 CTRL + SHIFT + PAGE UP 将选定内容扩展到当前窗口的顶部。 <br />编辑.扩展到下一字 CTRL + SHIFT + 右箭头键 将选定内容向右扩展一个单词的位置。 <br />编辑.向后扩展一个字列 CTRL + SHIFT + ALT + 右箭头键 将光标右移一个单词以扩展列选择。 <br />编辑.扩展到上一字 CTRL + SHIFT + 左箭头键 将选定内容向左扩展一个单词的位置。 <br />编辑.向前扩展一个字列 CTRL + SHIFT + ALT + 左箭头键 将光标左移一个单词以扩展列选择。</font> <br /><br />“文本操作”快捷键<br />下列快捷组合键可在文本编辑器中用于在打开的文档中删除、移动或者格式化文本。<br /><br />命令名 快捷键 说明 <br />编辑.分行 ENTER<br />SHIFT + ENTER 插入新行。 <br />编辑.字符转置 CTRL + T 交换插入点两边的字符。例如，AC| BD 变成 AB| CD。仅在文本编辑器中可用。 <br />编辑.清除书签 CTRL + K，CTRL + L 移除当前文档中所有未命名的书签。 <br />编辑.折叠到定义 CTRL + M，CTRL + O 自动确定在代码中创建区域的逻辑边界（如过程），然后隐藏它们。 <br />编辑.注释选定内容 CTRL + K，CTRL + C 使用编程语言的正确注释语法将代码的当前行标记为注释。 <br />编辑.完成单词 ALT + 右箭头键<br />CTRL + 空格键 显示基于当前语言的“完整单词”。 <br />编辑.删除 DELETE 删除光标右侧的一个字符。 <br />编辑.向后删除 BACKSPACE<br />SHIFT + BACKSPACE 删除光标左侧的一个字符。 <br />编辑.删除水平空白 CTRL + K，CTRL + \ 折叠选定内容中的空白，如果没有选定内容，则删除与光标相邻的空白。 <br />编辑.编排文档格式 CTRL + K，CTRL + D 按照“选项”对话框“文本编辑器”部分中语言的“格式设置”窗格上指定的设置，对语言应用缩进和空格格式设置。 <br />编辑.格式化选定内容 CTRL + K，CTRL + F 根据周围的代码行，正确缩进选定的代码行。 <br />编辑.隐藏选定内容 CTRL + M，CTRL + H 隐藏选定文本。信号图标标记隐藏文本在文件中的位置。 <br />编辑.插入制表符 TAB 将文本行缩进指定数量的空格，如 5 个。 <br />编辑.剪切行 CTRL + L 将所有选定的行剪切到“剪贴板”，若尚未选定任何内容，则将当前行剪切到剪贴板。 <br />编辑.删除行 CTRL + SHIFT + L 删除所有选定行；如果没有选定行，则删除当前行。 <br />编辑.上开新行 CTRL + ENTER 在插入点之上插入一个空行。 <br />编辑.下开新行 CTRL + SHIFT + ENTER 在插入点之下插入一个空行。 <br />编辑.行转置 SHIFT + ALT + T 将包含插入点的行移动到下一行之下。 <br />编辑.转换为小写 CTRL + U 将选定文本更改为小写字符。 <br />编辑.转换为大写 CTRL + SHIFT + U 将选定文本更改为大写字符。 <br />编辑.改写模式 INSERT 在插入和改写插入模式之间切换。仅在使用文本编辑器时可用。 <br />编辑.停止隐藏当前区域 CTRL + M，CTRL + U 移除当前选定区域的大纲显示信息。 <br />编辑.停止大纲显示 CTRL + M，CTRL + P 从整个文档中移除所有大纲显示信息。 <br />编辑.交换定位点 CTRL + R，CTRL + P 交换当前选定内容的定位点与结束点。 <br />编辑.左缩进 SHIFT + TAB 将选定行左移一个制表位。 <br />编辑.切换所有大纲显示 CTRL + M，CTRL + L 在隐藏和显示状态之间切换所有以前被标记为隐藏的文本部分。 <br />编辑.切换书签 CTRL + K，CTRL + K 在当前行处设置或移除书签。 <br />编辑.切换大纲显示展开 CTRL + M，CTRL + M 在隐藏和显示状态之间切换当前选定的隐藏文本部分。 <br />编辑.切换任务列表快捷方式 CTRL + K，CTRL + H 在当前行处设置或移除快捷方式。 <br />编辑.切换自动换行 CTRL + R，CTRL + R 启用或禁用编辑器中的自动换行。 <br />编辑.取消注释选定内容 CTRL + K，CTRL + U 从代码的当前行中移除注释语法。 <br />编辑.查看空白 CTRL + R，CTRL + W 显示或隐藏空格和制表符标记。 <br />编辑.字删除直至结尾处 CTRL + DELETE 删除插入点右侧的单词。 <br />编辑.字删除直至开始处 CTRL + BACKSPACE 删除插入点左侧的单词。 <br />编辑.字转置 CTRL + SHIFT + T 对调插入点两边的单词。例如，| End Sub 将更改为读取 Sub End|。 <br /><br />“窗口管理”快捷键<br />下列快捷组合键可在工具和文档窗口中用于进行移动、关闭或导航。<br /><br /><font style="BACKGROUND-COLOR: #000000" color="#ff1493">命令名 快捷键 说明 <br />视图.全屏 SHIFT + ALT + ENTER 在打开和关闭之间切换“全屏”模式。 <br />视图.向后定位 CTRL + - 返回到导航历史记录中的上一个文档或窗口。 <br />视图.向前定位 CTRL + SHIFT + - 向前移动到导航历史记录中的下一个文档或窗口。 <br />窗口.激活文档窗口 ESC 关闭菜单或对话框，取消正在进行的操作，或将焦点放在当前文档窗口中。 <br />窗口.关闭文档窗口 CTRL + F4 关闭当前 MDI 子窗口。 <br />窗口.关闭工具窗口 SHIFT + ESC 关闭当前工具窗口。 <br />窗口.移动到下拉栏 CTRL + F2 编辑器处于“代码”视图时将光标移动到下拉栏。 <br />窗口.下一个文档窗口 CTRL + F6<br />CTRL + TAB 逐个窗口地循环通过 MDI 子窗口。 <br />窗口.下一窗格 ALT + F6 移动到下一工具窗口。 <br />窗口.下一个拆分窗格 F6 移动到单个文档的拆分窗格视图的下一个窗格。 <br />窗口.下一选项卡 CTRL + PAGE DOWN 移动到文档或窗口中的下一个选项卡。 <br />窗口.上一个文档窗口 CTRL + SHIFT + F6<br />CTRL + SHIFT + TAB 移动到编辑器或设计器中的上一文档。 <br />窗口.上一窗格 SHIFT + ALT + F6 移动到上次选定的窗口。 <br />窗口.上一个拆分窗格 SHIFT + F6 移动到拆分窗格视图中的文档的上一个窗格。 <br />窗口.上一选项卡 CTRL + PAGE UP 移动到文档或窗口中的上一个选项卡。</font> <br /><br />“集成帮助”快捷键<br />下列快捷组合键可用于在“帮助”中的主题之间查看和移动。<br /><br /><font color="#800080">命令名 快捷键 说明 <br />帮助.目录 CTRL + ALT + F1 显示包含在 MSDN 中的文档的“目录”窗口。 <br />帮助.动态帮助 CTRL + F1 显示“动态帮助”窗口，该窗口根据产品中当前具有焦点的项显示不同的主题。 <br />帮助.F1帮助 F1 显示与选定的当前用户界面相对应的帮助主题。 <br />帮助.索引 CTRL + ALT + F2 显示包含在 MSDN 中的文档的“索引”窗口。 <br />帮助.索引结果 SHIFT + ALT + F2 显示“索引结果”窗口，它列出包含“索引”窗口中选定关键字的主题。 <br />帮助.下一个主题 ALT + 下箭头键 显示目录中的下一主题。仅在“帮助”(Web) 浏览器窗口中可用。 <br />帮助.上一个主题 ALT + 上箭头键 显示目录中的前一主题。仅在“帮助”(Web) 浏览器窗口中可用。 <br />帮助.搜索 CTRL + ALT + F3 显示“搜索”窗口，该窗口允许在包含于 MSDN 中的文档中搜索单词或词组。 <br />帮助.搜索结果 SHIFT + ALT + F3 显示“搜索结果”窗口，它显示包含从“搜索”窗口搜索的字符串的主题列表。 <br />帮助.窗口帮助 SHIFT + F1 显示与选定的当前用户界面相对应的帮助主题。</font> <br /><br />“对象浏览器”快捷键<br />下列快捷组合键可用于“对象浏览器”窗口。<br /><br />命令名 快捷键 说明 <br />编辑.查找符号 ALT + F12 显示“查找符号”对话框。 <br />编辑.转到声明 CTRL + F12 显示代码中选定符号的定义。 <br />编辑.转到定义 F12 显示代码中选定符号的声明。 <br />视图.查找符号结果 CTRL + ALT + F12 显示“查找符号结果”窗口。 <br />视图.对象浏览器 CTRL + ALT + J 显示“对象浏览器”，以查看可用于包的类、属性、方法、事件和常数以及项目中的对象库和过程。 <br />视图.对象浏览器向后 ALT + - 向后移动到“对象浏览器”的选择历史记录中的前一选定对象。 <br />视图.对象浏览器向前 SHIFT + ALT + - 向前移动到“对象浏览器”的选择历史记录中的下一对象。 <br /><br />“宏”快捷键<br />使用宏时可使用下列快捷组合键。<br /><br />命令名 快捷键 说明 <br />视图.宏资源管理器 ALT + F8 显示“宏资源管理器”窗口，它列出当前解决方案中所有可用的宏。 <br />工具.宏IDE ALT + F11 启动“Visual Studio 宏”-&gt;“宏 IDE”。 <br />工具.记录临时宏 CTRL + SHIFT + R 将环境置于“宏”记录模式。 <br />工具.运行临时宏 CTRL + SHIFT + P 回放记录的宏。 <br /><br />“工具窗口”快捷键<br />下列快捷组合键允许显示特定的工具窗口。<br /><br />命令名 快捷键 说明 <br />工具.命令窗口标记模式 CTRL + SHIFT + M 将“命令”窗口置于某种模式下，以允许在窗口中选择文本。 <br />视图.类视图 CTRL + SHIFT + C 显示“类视图”窗口。 <br />视图.命令窗口 CTRL + ALT + A 显示“命令”窗口，它允许您键入操作 IDE 的命令。 <br />视图.文档大纲 CTRL + ALT + T 显示“文档大纲”窗口，以查看当前文档的平面或层次大纲。 <br />视图.收藏夹 CTRL + ALT + F 显示“收藏夹”窗口，该窗口列出了 Web 页的快捷方式。 <br />视图.输出 CTRL + ALT + O 显示“输出”窗口以在运行时查看状态消息。 <br />视图.属性窗口 F4 显示“属性”窗口，该窗口列出当前选定项的设计时属性和事件。 <br />视图.属性页 SHIFT + F4 显示当前选定项的属性页。 <br />视图.资源视图 CTRL + SHIFT + E 显示“资源视图”窗口。 <br />视图.服务器资源管理器 CTRL + ALT + S 显示“服务器资源管理器”窗口，该窗口允许查看并操作数据库服务器、事件日志、消息队列、Web 服务和许多其他的操作系统服务。 <br />视图.显示Web浏览器 CTRL + ALT + R 显示“Web 浏览器”窗口，它允许您查看 Internet 上的页面。 <br />视图.解决方案资源管理器 CTRL + ALT + L 显示“解决方案资源管理器”，它列出当前解决方案中的项目和文件。 <br />视图.任务列表 CTRL + ALT + K 显示“任务列表”窗口，在此自定义、分类和管理任务、注释、快捷方式、警告和错误信息。 <br />视图.工具箱 CTRL + ALT + X 显示“工具箱”，它包含可包括在代码中或与代码一起使用的控件和其他项。 <br /><br />“项目”快捷键<br />下列快捷组合键可用于向项目中添加新项，生成项目，或者打开文件或项目。<br /><br />命令名 快捷键 说明 <br />生成.生成解决方案 CTRL + SHIFT + B 生成解决方案。 <br />生成.编译 CTRL + F7 创建一个对象文件，在其中包含选定文件的机器码、链接器指令、节、外部引用以及函数名或数据名。 <br />文件.添加现有项 SHIFT + ALT + A 显示“添加现有项”对话框，该对话框使您可以将现有文件添加到当前项目。 <br />文件.添加新项 CTRL + SHIFT + A 显示“添加新项”对话框，该对话框允许向当前的项目添加新文件。 <br />文件.新建文件 CTRL + N 显示“新建文件”对话框，在此可以选择要添加到当前项目中的新文件。 <br />文件.新建项目 CTRL + SHIFT + N 显示“新建项目”对话框，在此可创建项目并将其添加到当前解决方案。 <br />文件.打开文件 CTRL + O 显示“打开文件”对话框，在此可选择要打开的现有文件。 <br />文件.打开项目 CTRL + SHIFT + O 显示“打开项目”对话框，在此可将现有项目添加到解决方案。 <br />项目.重写 CTRL + ALT + INSERT 允许在派生类中重写基类方法。用于 C#。 <br /><br />杂项编辑器的快捷键<br />下列快捷组合键可用于快捷键编辑器或字符串编辑器。<br /><br />命令名 快捷键 说明 <br />编辑.新建快捷键 INSERT 添加一个新的快捷键项。仅在快捷键编辑器中可用。 <br />编辑.新建字符串 INSERT 在字符串表中添加新的项。仅用于字符串编辑器。 <br /><br /><a href="http://blog.csdn.net/qdzx2008/archive/2005/09/27/490880.aspx">http://blog.csdn.net/qdzx2008/archive/2005/09/27/490880.aspx</a><img src ="http://www.cppblog.com/mzty/aggbug/6306.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-04-26 12:55 <a href="http://www.cppblog.com/mzty/archive/2006/04/26/6306.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Visual Studio 2005中编译调试新功能 </title><link>http://www.cppblog.com/mzty/archive/2006/04/26/6304.html</link><dc:creator>梦在天涯</dc:creator><author>梦在天涯</author><pubDate>Wed, 26 Apr 2006 04:42:00 GMT</pubDate><guid>http://www.cppblog.com/mzty/archive/2006/04/26/6304.html</guid><wfw:comment>http://www.cppblog.com/mzty/comments/6304.html</wfw:comment><comments>http://www.cppblog.com/mzty/archive/2006/04/26/6304.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mzty/comments/commentRss/6304.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mzty/services/trackbacks/6304.html</trackback:ping><description><![CDATA[
		<a href="http://blog.csdn.net/qdzx2008/archive/2006/01/03/569462.aspx">http://blog.csdn.net/qdzx2008/archive/2006/01/03/569462.aspx</a>
		<br />
		<br />原文地址：<a href="http://jackyrong.cnblogs.com/archive/2005/11/15/277119.html" target="_blank"><font color="#002c99">http://jackyrong.cnblogs.com/archive/2005/11/15/277119.html</font></a><br /><br /><p id="fp">在日常的编程中，程序员经常离不开的工作之一，就是调试。当写好一段代码或程序后，在运行后总会出现这样那样的问题，比如各样的错误，程序员就必须进行调试，将这些错误排除。在最新出炉的Visual Studio 2005中，将提供十分强大而方便的调试功能，从而使程序员能节约时间，提高工作效率。本文中，将主要介绍Visual Studio 2005 在调试方面新增加的几个重要功能，并介绍它们的简单用法。<br />　　<br />　　Edit and Contiue功能<br /><br />　　在调试程序的时候，经常会遇到这样的情况：在调试一大段代码时，遇到了一个小的错误，比如参数的赋值错误了，这时候，往往希望能够马上将这些小的错误改正过来后，能够继续调试跟踪下去，而不用结束整个调试过程去修改。在Visual Studio 2003中，我们必须停止当前的调试，修改错误的地方，再重新编译，这样十分不方便。在Visual Studio 2005 中，提供了一个新的功能叫"edit and continue"，意思是说，当你在调试时，遇到小的错误需要马上修改后，可以进行编辑修改，然后继续往下调试，不需要结束整个调试的过程，当你修改后，调试器在后台进行了自动的编译，并且会执行新修改的代码，十分方便。下面举个例子进行说明。 <br /><br />　　打开Visual Studio 2005,使用c#建立一个winform窗体应用程序，在窗体中添加一个label标签，一个文本框，一个按钮，如下图所示，我们要实现的功能是，在文本框输入一些信息后，点按钮，会弹出一个消息框，显示的是刚才输入的信息。<br />    <br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="96" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de1.gif" width="314" onload="javascript:DrawImage(this);" border="0" /><br /><br /> 假如我们编写的代码如下所示，出现了一个小错误，把textbox1.text的内容当作字符串的一部分了，所以显示不出用户输入的信息。<br /><br /><script type="text/javascript"><![CDATA[
window.attachEvent("onload",function (){AutoSizeDIV('CODE_8096')})
]]&gt;</script></p><table class="code_head" cellspacing="0" cellpadding="0" width="80%" align="center" border="0"><tbody><tr><td>程序代码：</td><td align="right"><a href="javascript:CopyText(document.all.CODE_8096);"><font color="#002c99">[ 复制代码到剪贴板 ]</font></a></td></tr></tbody></table><div class="code_main" id="CODE_8096" style="OVERFLOW-Y: auto; OVERFLOW-X: hidden; HEIGHT: 79px">private void button1_Click(object sender, EventArgs e)<br />{<br />　//Show welcome message<br />　MessageBox.Show("Welcome textbox1.Text to Edit and Continue.");<br />} <br /></div><br /><br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="166" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de2.gif" width="300" onload="javascript:DrawImage(this);" border="0" /><br />现在，如果我们在调试时遇到了这个错误，则可以使用edit and continue功能来进行改正。<br /><br />　　首先，按F7切换到代码视图，在MessageBox.Show这一行设置断点，之后按F5运行程序，当在文本框输入字符串时，由于设置了中断，光标停留在messagebox.show这行上，这时，我们可以修改代码，修改为：<br />private void button1_Click(object sender, EventArgs e)<br />{<br />　MessageBox.Show("Welcome " + textbox1.Text +" to Edit and Continue.");<br />} <br /><br />　　修改完后，继续按F5运行，这时候，则会显示正确的结果了，如下图，而不需要使用以往的"stop debugging"的功能先停止调试再修改程序。<br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="170" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de3.gif" width="302" onload="javascript:DrawImage(this);" border="0" /><br /><br /> 可视化调试器(Debugging Visualizers)<br /><br />　　在调试的时候，我们遇到的一个很麻烦的问题，就是有的时候很难看到某些参数的值。比如当你设置了一个断点去监测一个dataset,并且想看dataset里的每个datatable的数据，这在Visual Studio 2003中，是十分麻烦的，必须在auto/locals的监视窗口中，一层层地展开去看其值。在Visual Studio 2005中，为解决这个问题，新增加了叫"debugging visualizers"(可视化调试器)的功能，该功能可以在调试状态时，很容易方便地以各类形式，比如文本,html,xml等方式查看各种参数。<br /><br />　　在各类的监视窗口中，比如在autos,locals,watch和quickwatch 中都可以调用可视化调试器,方法是在某个需要监视的参数旁边，点击那个放大镜图标，就可以在打开的可视化调试器中看到该参数的详细情况，如下图所示：<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="201" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de4.gif" width="509" onload="javascript:DrawImage(this);" border="0" /><br /><br />利用可视化调试器，就可以很方便地查看比如dataset类型的数据，如下图所示：<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="313" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de5.gif" width="504" onload="javascript:DrawImage(this);" border="0" /><br /><br />Data Tips<br /><br />　　在Visual Studio 2005中，在调试方面，还新增了"data tips(数据提示)"的功能。当在调试程序期间，只需要将光标移到代码中某个需要监视的参数上，系统就会自动显示与该参数相关联的一些很有用的信息，比如相关的属性，以及当前该参数的值。在Visual Studio 2003中，也有该功能，但提供的信息比现在的2005少很多。<br /><br />　　我们依然以上面"edit and continue"使用的例子来说明。我们将断点设在MessageBox.Show这一行，F5运行程序，当在文本框输入文字并按确定按钮后，程序自动中断，这时，将光标移到textbox1.text这个位置，系统就会调用data tips功能，如下图所示显示出与textbox文本框控件相关的一些属性以及这些属性此时对应的值。<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="253" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de6.gif" width="518" onload="javascript:DrawImage(this);" border="0" /><br /><br />   在data tip的功能中，还可以继续使用edit and continue的功能，只需要在需要的地方鼠标右键就可以弹出如下图的菜单，可以编辑该值。<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="199" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de7.gif" width="305" onload="javascript:DrawImage(this);" border="0" /><br /><br />  Exception Assistant(异常助手) <br /><br />　　在Visual Studio .net 2003中，当程序运行出现异常时，系统会显示一个异常信息对话框，询问是否停止程序执行或继续运行程序，但并没有提供给开发者更多的关于异常的信息。在Visual Studio .net 2005中，提供了 Exception Assistant(异常助手)的新功能，可以显示丰富的关于异常方面的信息，帮助开发者调试，如下图<br />   <br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="284" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de8.gif" width="417" onload="javascript:DrawImage(this);" border="0" /><br /> 在上图中，显示的是一个sqlException，是由于超时连接而造成的。在异常助手的窗口中,显示了关于该异常的详细信息，还可以将这些信息复制到剪贴版中，当选择view detail时，会弹出如下图所示的窗口，进一步显示关于该异常的详细信息<br /><br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="291" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de9.gif" width="498" onload="javascript:DrawImage(this);" border="0" /><br /><br /> Just My Code Debugging<br /><br />　　在调试代码中，我们经常会遇到这样的问题，有时我们引用了一些其他工具包或者类库（如Microsoft提供的Enterprise Library）,而在调试时，我们其实是不需要跟踪调试这些代码的，因为它们都已经证明是正确的。在Visual Studio 2003中，处理这类问题我们的方法一般是使用F10跳过它们，但一旦工程庞大的话，这样做十分麻烦。在Visual Studio 2005中，新增加了Just My Code debugging(JMC)的新特性，可以让开发者自己定制哪些代码是需要调试，哪些代码是永远不需要调试的，这样可以节省大量的时间。<br /><br />　　JMC功能由两方面来实现。首先，如果一个工程是以release方式进行编译构建的话（就是工程中，没有pdb文件），调试器会将其认为是非用户代码，那么在调试运行时，就根本不会进入该工程中进行调试。其次，可以使用System.Diagnostics命名空间里的DebuggerNonUserCodeAttribute属性，将其应用在希望不进行调试的代码段中。<br /><br />　　下面举一个例子来说明。下面的代码段中，有两个静态方法UserCode()和NonUserCode(),其中，在NonUserCode()中，是应用了DebuggerNonUserCode的属性，这表明这段代码将在调试运行时，调试器不会进入其中。将断点设置在其中的第9行，运行程序，程序会在第一个UserCode()里中断，现在试着用F11继续单步跟踪，会发现系统在进入usercode()方法中运行后，并没有进入到NonUserCode()里运行。<br /><br />using System;<br />using System.Diagnostics;<br />class Program<br />{<br />static void Main(string[] args)<br />{<br />// Step into F11 from here<br />UserCode();// Place break point on this line<br />NonUserCode();<br />UserCode();<br />}<br />static void UserCode()<br />{<br />Console.WriteLine("This is a call from user Code");<br />}<br />// Attribute to indicate the Debugger to jump<br />// over this method<br />[DebuggerNonUserCode]<br />static void NonUserCode()<br />{<br />Console.WriteLine("This is a call fron Non User Code");<br />}<br />} <br />编辑时对象识别<br /><br />　　在Visual Studio 2005中，新引入了"Object Identity While Debugging"的概念，也就是说，系统给在调试阶段的每个对象，都可以赋予一个别名，在调试时，直接引用该别名就可以了。<br /><br />　　假设在调试的时候，需要跟踪比如dataset或者hashtable等对象，这些对象中包含了很多其他的子对象，如果想对这些数量众多的子对象进行跟踪的话，将十分麻烦。在Visual Studio 2005中，可以使用object identity(对象标识)的方法去标记每一个对象，<br /><br />　　比如，在一个windows应用程序中，创建了一个dataset,并将其绑定到datagridview中去。如将sql server 的northwind数据库中的orders和orderdetail表中的数据读出填充到dataset里去，则在调试时，设置一个断点放在dataset里填充了数据之后的那行，这时，在监视窗口中，鼠标展开this.northwindData这个dataset，如下图所示，找到orders这个table，然后鼠标右键,会弹出一个菜单，选择其中的" Make Object ID".<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="226" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de10.gif" width="503" onload="javascript:DrawImage(this);" border="0" /><br /><br />这时，会将orders这个参数以1#的别名方式命名（见下图），并且在整个应用程序中，只要在dataset的生存期，都可以以1#的方式访问它。<br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="148" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de11.gif" width="518" onload="javascript:DrawImage(this);" border="0" /><br />下图的代码演示了如何在immediate监视窗口中，通过使用object 标识，查看某一个表中所有记录的方法。要注意的是，必须将其显式类型转换为DataApp.NorthwidDataSet.OrdersDataTable。通过使用object 标识的好处是，可以在调试阶段，不需要在描述某个参数时，再用冗余的命名方法表示了（比如可以用#1来代替this.NorthwidDataSet.Orders）<br /><br /><br /><img onmouseover="this.style.cursor='hand';" style="CURSOR: hand" onclick="window.open(this.src);" height="51" alt="按此在新窗口打开图片" src="http://jackyrong.cnblogs.com/images/cnblogs_com/jackyrong/de12.gif" width="422" onload="javascript:DrawImage(this);" border="0" /><img src ="http://www.cppblog.com/mzty/aggbug/6304.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mzty/" target="_blank">梦在天涯</a> 2006-04-26 12:42 <a href="http://www.cppblog.com/mzty/archive/2006/04/26/6304.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>