<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Spec Explorer 团队博客</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/sechina/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/sechina/feed.xml</link>
    <description>基于模型的测试工具</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:27:47 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Spec Explorer 2010 3.5发布了！</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2010-3-5</link>
      <pubDate>Mon, 18 Apr 2011 08:13:14 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2011/04/18/spec-explorer-2010-3-5/</guid>
      <description><![CDATA[我们非常高兴的宣布Spec Explorer 2010 3.5版发布了。    新的3.5版包含了新的功能，持续改进的文档，以及多于60个bug的修正。   3.5版本包含以下功能：...]]></description>
      <content:encoded><![CDATA[<p>我们非常高兴的宣布Spec Explorer 2010 3.5版发布了。    <br />新的3.5版包含了新的功能，持续改进的文档，以及多于60个bug的修正。 </p>  <p>3.5版本包含以下功能：</p>  <ul>   <li>模型更新检查： </li> </ul>  <blockquote>   <p>模型更新检查能够识别必要的模型更新，从而决定是否重新探索模型。对于特定的machine，如果模型源代码，cord脚本或者模型工程中引用的其他输入文件发生改变，Spec Explorer会开始一次新的探索；否则将会使用已有的探索结果用于显示，测试代码生成或者用户定制处理。Spec Explorer也添加了一个按钮用于强制重新探索。</p> </blockquote>  <ul>   <li>多machine处理： </li> </ul>  <blockquote>   <p>Spec Explorer加入了对多machine的支持，现在用户可以方便的选定多个machine并进行模型探索，测试代码生成或者用户定制处理的工作。</p> </blockquote>  <ul>   <li>cord上下文菜单： </li> </ul>  <blockquote>   <p>Spec Explorer对cord脚本加入了&quot;”Go To Definition“这个菜单项，用户可以方便的通过这个菜单项或者快捷键F12导航到相应的cord配置定义或者是machine定义。 </p> </blockquote>  <p>以下是最新版本的链接：</p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166911">Spec Explorer主页</a></p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166135">Release Notes</a></p>  <p><a href="https://social.msdn.microsoft.com/Forums/en-US/specexplorer/threads">论坛</a></p>  <p><a href="https://blogs.msdn.com/SpecExplorer">英文blog</a></p>  <p><a href="https://msdn.microsoft.com/en-us/library/ee620411.aspx">MSDN文档</a></p>  <p>Spec Explorer 2010 3.5只能在Visual Studio 2010 professional版或以上版本使用，您可以通过<a href="https://www.microsoft.com/visualstudio/en-us/download">这里</a>得到Visual Studio 2010的90天试用版。</p>  <p>欢迎您提出宝贵的意见和建议！</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer 2010 3.4发布了</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2010-3-4</link>
      <pubDate>Fri, 07 Jan 2011 00:15:25 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2011/01/07/spec-explorer-2010-3-4/</guid>
      <description><![CDATA[我们非常高兴的宣布Spec Explorer 2010 3.4版发布了。    新的3.4版包含了新的功能，持续改进的文档，以及多于50个bug的修正。       3.4版本包含以下功能：...]]></description>
      <content:encoded><![CDATA[<p>我们非常高兴的宣布Spec Explorer 2010 3.4版发布了。    <br />新的3.4版包含了新的功能，持续改进的文档，以及多于50个bug的修正。     <br /></p>  <p>3.4版本包含以下功能：</p>  <ul>   <li>动态遍历： </li> </ul>  <blockquote>   <p>动态遍历提供了一种新的测试用例生成机制，用户可以定制遍历策略，并且在测试运行时对探索结果进行遍历并同时调用相应的测试方法。</p> </blockquote>  <ul>   <li>验证性能改进： </li> </ul>  <blockquote>   <p>Cord脚本的验证过程性能有了明显改进</p> </blockquote>  <ul>   <li>部分探索结果呈现： </li> </ul>  <blockquote>   <p>新版中用户点击Stop按钮或者探索过程超过了配置的时限，Spec Explorer会显示截止目前的探索结果</p> </blockquote>  <ul>   <li>基于多个namespace / type的模型构建： </li> </ul>  <blockquote>   <p>新版中模型构建不再只能基于单个namespace / type，改为基于一个逗号分隔的namespace / type 名称列表进行构建</p> </blockquote>  <ul>   <li>基于完全限定名的静态Action调用： </li> </ul>  <blockquote>   <p>静态Action调用被加入了完全限定名的支持，在新版中使用者可以使用不同类型的同名静态Action</p> </blockquote>  <ul>   <li>SpecExplorer.exe加入脚本验证任务： </li> </ul>  <blockquote>   <p>脚本验证任务被加入SpecExplorer.exe</p> </blockquote>  <p>以下是最新版本的链接：</p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166911" target="_blank">Spec Explorer主页</a></p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166135" target="_blank">Release Notes</a></p>  <p><a href="https://social.msdn.microsoft.com/Forums/en-US/specexplorer/threads" target="_blank">论坛</a></p>  <p><a href="https://blogs.msdn.com/SpecExplorer" target="_blank">英文blog</a></p>  <p><a href="https://msdn.microsoft.com/en-us/library/ee620411.aspx" target="_blank">MSDN文档</a></p>  <p>Spec Explorer 2010 3.4只能在Visual Studio 2010 professional版或以上版本使用，您可以通过<a href="https://www.microsoft.com/visualstudio/en-us/download" target="_blank">这里</a>得到Visual Studio 2010的90天试用版。</p>  <p>希望您能够喜欢我们最新的Spec Explorer版本，也欢迎您提出宝贵的意见和建议，让我们能够在未来发布更好的产品。</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer 2010 3.3版成为Visual Studio Power Tool</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2010-3-3visual-studio-power-tool</link>
      <pubDate>Mon, 18 Oct 2010 20:22:59 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2010/10/18/spec-explorer-2010-3-3visual-studio-power-tool/</guid>
      <description><![CDATA[我们非常高兴的宣布Spec Explorer发布了3.3版本，该版本从DevLab迈向了Visual Studio Power Tool，您可以在Visual Studio...]]></description>
      <content:encoded><![CDATA[<p>我们非常高兴的宣布Spec Explorer发布了3.3版本，该版本从DevLab迈向了Visual Studio Power Tool，您可以在Visual Studio Gallery中找到我们新的<a href="https://go.microsoft.com/fwlink/?LinkID=166911" target="_blank">主页</a>。</p>  <p>Spec Explorer 2010包含了新的功能，持续改进的文档，以及多于100个bug的修正。</p>  <p>3.3版本包含以下功能：</p>  <ul>   <li>实时测试</li> </ul>  <blockquote>   <p>实时测试功能让用户可以直接使用模型进行测试，而无需生成测试代码。Action的选择将由适配器和待测系统共同决定。</p> </blockquote>  <ul>   <li>状态搜索</li> </ul>  <blockquote>   <p>用户可以在探索结果图上搜索状态，从一定程度上解决了模型难以调试的问题。</p> </blockquote>  <ul>   <li>probe记录</li> </ul>  <blockquote>   <p>probe的值将会被生成到测试代码中，用户可以通过观察测试日志中的probe信息分析测试过程，解决了之前只有状态ID难以分析的问题。</p> </blockquote>  <ul>   <li>测试方法定制</li> </ul>  <blockquote>   <p>通过使用新的定制开关，用户可以选择生成测试方法的返回值，返回类型甚至声称静态测试方法。该功能使得Spec Explorer可以生成适用于更多测试平台的代码，而非局限于Visual Studio的测试环境。</p> </blockquote>  <p>另外，我们也发布了Spec Explorer的<a href="https://go.microsoft.com/fwlink/?LinkID=202596" target="_blank">UML扩展包</a>，支持通过一个Sequence Diagram进行基于模型的测试。</p>  <p>以下是最新版本的链接：</p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166911" target="_blank">Spec Explorer主页</a></p>  <p><a href="https://go.microsoft.com/fwlink/?LinkID=166135" target="_blank">Release Notes</a></p>  <p><a href="https://social.msdn.microsoft.com/Forums/en-US/specexplorer/threads" target="_blank">论坛</a></p>  <p><a href="https://blogs.msdn.com/SpecExplorer" target="_blank">英文blog</a></p>  <p><a href="https://msdn.microsoft.com/en-us/library/ee620411.aspx" target="_blank">MSDN文档</a></p>  <p>Spec Explorer 2010 3.3只能在Visual Studio 2010 professional版或以上版本使用，您可以通过<a href="https://www.microsoft.com/visualstudio/en-us/download" target="_blank">这里</a>得到Visual Studio 2010的90天试用版。</p>  <p>希望您能够喜欢我们最新的Spec Explorer版本，也欢迎您提出宝贵的意见和建议，让我们能够在未来发布更好的产品。</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer 2010 3.2发布了！</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2010-3-2</link>
      <pubDate>Mon, 19 Apr 2010 22:49:27 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2010/04/19/spec-explorer-2010-3-2/</guid>
      <description><![CDATA[Spec Explorer 2010 发布最新的3.2版本了。  新的Spec Explorer较前一版本又新增和改善了一些功能，改进了文档，并修正了超过110个bug。新版Spec...]]></description>
      <content:encoded><![CDATA[<p>Spec Explorer 2010 发布最新的3.2版本了。</p>  <p>新的Spec Explorer较前一版本又新增和改善了一些功能，改进了文档，并修正了超过110个bug。新版Spec Explorer运行在Visual Studio 2010 Professional及以上版本。</p>  <p>新功能概述：</p>  <ul>   <li>New Model Wizard </li> </ul>  <blockquote>   <p>新的建模向导将旧有的基本解决方案(Spec Explorer Base Solution)模板和模型工程（Spec Explorer Model Project）模板进行了整合，使用者可以更方便的新建和添加Spec Explorer工程。</p> </blockquote>  <ul>   <li>Choice API </li> </ul>  <blockquote>   <p>Choice API对建模待测试系统的非确定性行为进行了更好的支持。使用者不再需要把一个Action拆分成调用和返回两个方法，而是在一个方法内部通过使用Choice API对待测试系统可能存在多个响应的情况进行建模。</p> </blockquote>  <ul>   <li>SpecExplorer.exe </li> </ul>  <blockquote>   <p>新的SpecExplorer.exe将支持最新的探索结果格式，并对用户定制的Post-Exploration任务扩展进行了支持。</p> </blockquote>  <ul>   <li>Improved Documentation </li> </ul>  <blockquote>   <p>Spec Explorer的文档持续更新中，在3.2中尤其更新了Cord脚本语言的描述。</p> </blockquote>  <p>Spec Explorer可以从微软DevLabs的<a href="https://msdn.microsoft.com/en-us/devlabs/ee692301.aspx" target="_blank">主页</a>进行下载。</p>  <p>浏览最新的<a href="https://go.microsoft.com/fwlink/?LinkID=166135">Release Notes</a>获得更详细的关于安装，功能和已知问题的信息。     <br />更多的信息请浏览<a href="https://social.msdn.microsoft.com/Forums/en-US/specexplorer">Spec Explorer论坛</a>，团队博客（<a href="https://blogs.msdn.com/sechina">中文</a>/<a href="https://blogs.msdn.com/SpecExplorer/">英文</a>），和<a href="https://msdn.microsoft.com/en-us/library/ee620411.aspx">MSDN在线帮助</a></p>  <p>需要注意的是，Spec Explorer 2010 3.2版本只能运行在Visual Studio 2010的发行版本上，而不能运行于Visual Studio2010的Beta 1, Beta 2和Release Candidate版本，以及Visual Studio 2008的任何版本。Visual Studio 2010的90天试用版可以<a href="https://www.microsoft.com/visualstudio/en-us/download" target="_blank">下载</a>。</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer在线课程</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer</link>
      <pubDate>Mon, 19 Apr 2010 20:57:16 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2010/04/19/spec-explorer/</guid>
      <description><![CDATA[Channel 9上现在有完整的使用Spec Explorer进行基于模型测试的在线视频课程了！这是Spec...]]></description>
      <content:encoded><![CDATA[<p>Channel 9上现在有完整的使用Spec Explorer进行基于模型测试的在线视频课程了！这是Spec Explorer美国团队的架构师Wolfgang和高级项目经理Nico在Redmond微软总部为期两天半的课程录像。    <br />整个培训课程长达8小时，我们将其分成了四节课，每节课有四部分。 </p>  <p><a href="https://channel9.msdn.com/tags/SpecExplorerClassSession1/" target="_blank">课程1</a> </p>  <p><a href="https://channel9.msdn.com/tags/SpecExplorerClassSession2/" target="_blank">课程2</a> </p>  <p><a href="https://channel9.msdn.com/tags/SpecExplorerClassSession3/" target="_blank">课程3</a> </p>  <p><a href="https://channel9.msdn.com/tags/SpecExplorerClassSession4/" target="_blank">课程4</a> </p>  <p>屏幕截图可能不够清晰，我们以后将用更高清晰度的录像代替，希望大家理解</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer 2010 3.1发布了！</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2010-3-1</link>
      <pubDate>Tue, 23 Feb 2010 22:00:55 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2010/02/23/spec-explorer-2010-3-1/</guid>
      <description><![CDATA[朋友们好，Spec Explorer 2010发布新的3.1版本了！  Spec Explorer 2010 3.1版本是基于Visual Studio 2010...]]></description>
      <content:encoded><![CDATA[<p>朋友们好，Spec Explorer 2010发布新的3.1版本了！</p>  <p>Spec Explorer 2010 3.1版本是基于Visual Studio 2010 RC的，这一版本较前一版本拥有更强大的功能，并修正了超过220个bug。</p>  <p>特别需要注意的是建模属性和建模类都进行了重命名，新的命名将更为准确和清晰。如果用户继续使用过期的旧属性名和类名（例如Microsoft.Modeling.Contracts类），Spec Explorer会产生警告信息。 </p>  <p>新增功能概述：</p>  <ul>   <li>Flexible test naming and attributes      <br />3.1版本引入了新的Cord开关，用于更好的控制测试用例的名称与属性，从而生成基于不同测试框架的测试代码。用户甚至可以使用系统的环境变量或者Spec Explorer的内置变量来给这些开关赋值。 </li>    <li>Bounded repetition machine      <br />新的Cord引入了一种新的machine，用于表示重复特定次数范围内的行为。 </li>    <li>New project creation      <br />新的Spec Explorer工程创建模板可以创建一个简单的模型工程，该工程可以被添加到已有的解决方案中或者独立成为一个解决方案。 </li>    <li>Construct tag and switch completion      <br />Cord目前支持Construct声明和开关声明的自动完成。 </li>    <li>F1 Help      <br />在Spec Explorer的任何一个窗口中按下F1键，Visual Studio 2010内置的帮助系统都会显示出相应的帮助信息。 </li>    <li>Help integration      <br />Spec Explorer的文档与Visual Studio 2010的帮助管理器整合，同时支持在线MSDN帮助和本地帮助。 </li>    <li>Exploration progress      <br />Spec Explorer改进了探索过程中的进度显示。 </li>    <li>User-customized post processing      <br />用户可定制Post-Exploration的任务，基于当前探索结果生成报表，报告等自己关心的信息。 </li> </ul>  <p>Spec Explorer 3.1可以从微软DevLabs的<a href="https://msdn.microsoft.com/en-us/devlabs/ee692301.aspx" target="_blank">Spec Explorer主页</a>下载     <br />浏览最新的<a href="https://go.microsoft.com/fwlink/?LinkID=166135" target="_blank">Release Notes</a>获得更详细的关于安装，功能和已知问题的信息。     <br />更多的信息请浏览<a href="https://social.msdn.microsoft.com/Forums/en-US/specexplorer" target="_blank">Spec Explorer论坛</a>，团队博客（<a href="https://blogs.msdn.com/sechina" target="_blank">中文</a>/<a href="https://blogs.msdn.com/SpecExplorer/" target="_blank">英文</a>），和<a href="https://msdn.microsoft.com/en-us/library/ee620411.aspx" target="_blank">MSDN在线帮助</a></p>]]></content:encoded>
    </item>
    <item>
      <title>使用Spec Explorer对象模型：基础篇</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-2</link>
      <pubDate>Sun, 27 Dec 2009 21:36:40 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2009/12/27/spec-explorer-2/</guid>
      <description><![CDATA[一些使用者希望能够自己处理Spec Explorer产生的探索结果，而不是其自带的功能。Spec Explorer的对象模型可以用于此类处理，本篇博客将对这种用法进行一个基础介绍。  当Spec...]]></description>
      <content:encoded><![CDATA[<p>一些使用者希望能够自己处理Spec Explorer产生的探索结果，而不是其自带的功能。Spec Explorer的对象模型可以用于此类处理，本篇博客将对这种用法进行一个基础介绍。</p>  <p>当Spec Explorer对状态空间进行探索或者生成测试代码时，探索结果将被存在一个扩展名为seexpl的文件中，这个文件实际上是一些表示探索结果的xml文件的zip包。seexpl文件的内容在Visual Studio里面会显示为状态图，以SMB2 sample（安装Spec Explorer以后sample也随之安装）为例，TestSuite这个machine的探索结果如下图所示：</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_12%5B1%5D_2.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_12%5B1%5D_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image_12[1]" border="0" alt="image_12[1]" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_12%5B1%5D_thumb.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_12%5B1%5D_thumb.png" width="645" height="665" /></a></p>  <p>除了使用Visual Studio打开seexpl文件外，用户可以用自己的程序来打开。这里需要用到Microsoft.SpecExplorer.ObjectModel这个assembly。</p>  <p>让我们来实现一个输出探索结果统计信息（比如覆盖的需求，action的序列等等）的小程序。首先，创建一个console应用程序并把ObjectModel加到引用中。</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_2%5B1%5D_2.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_2%5B1%5D_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image_2[1]" border="0" alt="image_2[1]" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_2%5B1%5D_thumb.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_2%5B1%5D_thumb.png" width="606" height="491" /></a> 对象模型就包含在Microsoft.SpecExplorer.ObjectModel这个命名空间中。</p>  <div id="codeSnippetWrapper">   <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">using</span> System;<br /><span style="color: #0000ff">using</span> System.Collections.Generic;<br /><span style="color: #0000ff">using</span> System.Linq;<br /><span style="color: #0000ff">using</span> System.Text;<br /><br /><span style="color: #0000ff">using</span> Microsoft.SpecExplorer.ObjectModel;<br /><br /><span style="color: #0000ff">namespace</span> TransitionSystemDemo<br />{<br />    <span style="color: #0000ff">class</span> Program<br />    {<br />      ...<br /></pre>

  <br /></div>

<p>最上层表示探索结果的对象被称为transition system，这个名字来源于探索被表示为一组状态以及所有状态之间的迁移（其标签即为action）。transition system这一对象可以被一个叫做TransitionSystemLoader的类加载，代码示例如下：</p>

<div id="codeSnippetWrapper">
  <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)<br />{<br />    <span style="color: #0000ff">if</span> (args.Length != 1)<br />    {<br />        Console.WriteLine(<span style="color: #006080">&quot;usage: transitionsystemdemo &lt;pathtoseexpl&gt;&quot;</span>);<br />        Environment.Exit(1);<br />    }<br />    <span style="color: #0000ff">try</span><br />    {<br />        var loader = <span style="color: #0000ff">new</span> ExplorationResultLoader(args[0]);<br />        TransitionSystem tsys = loader.LoadTransitionSystem();<br />        Process(tsys);<br />    }<br />    <span style="color: #0000ff">catch</span> (Exception e)<br />    {<br />        Console.WriteLine(<span style="color: #006080">&quot;failed: &quot;</span> + e.Message);<br />        Environment.Exit(2);<br />    }<br />}<br /></pre>

  <br /></div>

<p>Process这个方法将稍后定义。我们首先看看怎么通过一个方法调用输出transition system的统计信息。在这里我们用到LINQ来方便的计算所有被覆盖或者假定被覆盖的需求列表。</p>

<div id="codeSnippetWrapper">
  <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> PrintStatistics(TransitionSystem tsys)<br />{<br />    Console.WriteLine(<span style="color: #006080">&quot;{0} states ({1} initial), {2} steps&quot;</span>,<br />        tsys.States.Length, tsys.InitialStates.Length, tsys.Transitions.Length);<br />    var captured =<br />        tsys.Transitions.Aggregate(<br />                <span style="color: #0000ff">new</span> <span style="color: #0000ff">string</span>[0] <span style="color: #0000ff">as</span> IEnumerable&lt;<span style="color: #0000ff">string</span>&gt;,<br />                (cs, tr) =&gt; cs.Concat(tr.CapturedRequirements).Concat(tr.AssumeCapturedRequirements))<br />                .Distinct()<br />                .OrderBy(x =&gt; x);<br />    Console.WriteLine(<span style="color: #006080">&quot;captured: &quot;</span>);<br />    <span style="color: #0000ff">foreach</span> (var req <span style="color: #0000ff">in</span> captured)<br />        Console.WriteLine(<span style="color: #006080">&quot;  &quot;</span> + req);<br />}<br /></pre>

  <br /></div>

<p>transition system有三个基本的属性，可用于遍历：</p>

<ul>
  <li>States：transition system中所有状态的数组。数组中的每一个元素是一个表示状态的对象，含有诸如状态类型，状态标签等信息。 </li>

  <li>InitialStates：transition system中所有初始状态的数组。如果该transition system表示的是一组测试，则每一个测试用例都会有一个初始状态。 </li>

  <li>Transitions：transition system中所有状态迁移的数组。数组中的每一个元素是一个表示状态前一的对象，含有诸如源状态，目标状态，需求覆盖等信息。 </li>
</ul>

<p>对SMB2 sample的TestSuite探索结果运行上述程序，结果如下：</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_4%5B1%5D_2.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_4%5B1%5D_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image_4[1]" border="0" alt="image_4[1]" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_4%5B1%5D_thumb.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_4%5B1%5D_thumb.png" width="632" height="351" /></a> 计算需求非常的容易，现在让我们来计算action的序列，这一部分会稍微复杂一些：</p>

<ul>
  <li>我们的程序需要处理任意的transition system，则可能会遇到有环的情况。我们将通过一旦发现环就立刻停止遍历来实现。 </li>

  <li>transition system是可能包含分支（同一源状态存在多个状态迁移）的，即便是已经分拆成测试用例的transition system。我们将以一种类似cord语法的形式生成序列，比方说action A到达某个状态，而该状态之后B和C都被允许，则我们生成A;(B|C)的形式。 </li>
</ul>

<p>代码如下：</p>

<div>
  <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> PrintPatterns(TransitionSystem tsys)<br />{<br />    <span style="color: #0000ff">foreach</span> (var stateLabel <span style="color: #0000ff">in</span> tsys.InitialStates)<br />    {<br />        Console.WriteLine(<span style="color: #006080">&quot;Starting in state {0}:&quot;</span>, stateLabel);<br />        Console.WriteLine(ToPattern(tsys, <span style="color: #0000ff">new</span> HashSet&lt;State&gt;(), GetState(tsys, stateLabel)));<br />    }<br />}<br /><br /><span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> ToPattern(TransitionSystem tsys, HashSet&lt;State&gt; visiting, State state)<br />{<br />    <span style="color: #0000ff">if</span> (state.RepresentativeState != <span style="color: #0000ff">null</span>)<br />        <span style="color: #008000">// skip intermediate state</span><br />      <span style="color: #0000ff">return</span> ToPattern(tsys, visiting, GetState(tsys, state.RepresentativeState));<br />    <span style="color: #0000ff">if</span> (visiting.Contains(state))<br />        <span style="color: #008000">// Stop at cycle</span><br />        <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;&quot;</span>;<br />    visiting.Add(state);<br />    <span style="color: #008000">// compute successor</span><br />    var successors = GetSuccessors(tsys, state).Select(tr =&gt; ToPattern(tsys, visiting, tr)).ToArray();<br />    visiting.Remove(state);<br />    <span style="color: #0000ff">if</span> (successors.Length == 0)<br />        <span style="color: #008000">// end state</span><br />        <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;&quot;</span>;<br />    <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (successors.Length == 1)<br />        <span style="color: #0000ff">return</span> successors[0];<br />    <span style="color: #0000ff">else</span><br />        <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;(&quot;</span> + <span style="color: #0000ff">string</span>.Join(<span style="color: #006080">&quot;|\r\n&quot;</span>, successors) + <span style="color: #006080">&quot;)&quot;</span>;<br />}<br /><br /><span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> ToPattern(TransitionSystem tsys, HashSet&lt;State&gt; visiting, Transition tr)<br />{<br />    var continuation = ToPattern(tsys, visiting, GetState(tsys, tr.Target));<br />    <span style="color: #0000ff">if</span> (continuation != <span style="color: #006080">&quot;&quot;</span>)<br />        <span style="color: #0000ff">return</span> tr.Action.Text + <span style="color: #006080">&quot;;\r\n&quot;</span> + continuation;<br />    <span style="color: #0000ff">else</span><br />        <span style="color: #0000ff">return</span> tr.Action.Text;<br />}<br /><br /><span style="color: #0000ff">static</span> State GetState(TransitionSystem tsys, <span style="color: #0000ff">string</span> stateLabel)<br />{<br />    <span style="color: #0000ff">return</span> tsys.States.First(state =&gt; state.Label == stateLabel);<br />}<br /><br /><span style="color: #0000ff">static</span> IEnumerable&lt;Transition&gt; GetSuccessors(TransitionSystem tsys, State state)<br />{<br />    <span style="color: #0000ff">return</span> tsys.Transitions.Where(tr =&gt; tr.Source == state.Label);<br />}</pre>
</div>

<div>需要说明的是：</div>

<ul>
  <li>每一个状态都有一个RepresentativeState的属性。这个属性和symbolic transition system有关，symbolic的相关内容超出了本篇博客的范畴，我们将在之后的文章中进行解释。只需要记住，当我们访问一个含有RepresentativeState的状态时，我们跳过该状态，并从RepresentativeState继续遍历。 </li>

  <li>我们记录已经访问过的状态，所以可以方便的发现环。 </li>

  <li>我们使用tr.Action.Text来输出action，这个信息和我们在Visual Studio里面显示的action标签是一样的。但是我们必须明白，一个action对象不仅仅是标签那么简单，它含有更多的信息，只是我们这里不会用到。 </li>

  <li>计算状态和状态迁移时，我们搜索了transition system多次，这种方法很低效。实际的程序中，用户可能更愿意缓存这些信息。 </li>
</ul>

<div>&#160;</div>

<div>对SMB2 Sample的TestSuite运行上述程序，则输出如下：</div>

<div><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_10%5B1%5D_2.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_10%5B1%5D_2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image_10[1]" border="0" alt="image_10[1]" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_10%5B1%5D_thumb.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/7607f00c44f6_9970/image_10%5B1%5D_thumb.png" width="660" height="317" /></a> 在transition system中，还有好多可利用的东西我们没有在这里展示。最酷的或许就是所有有关action和action参数的信息都可以直接被转变为反射信息和LINQ表达式，这样一个用户就可以写出基于transition system的测试执行器。我们会在以后的博客中继续介绍。</div>

<div>本篇博客的整个示例代码如下：</div>

<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 80.33%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; height: 121px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
  <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"><span style="color: #0000ff">using</span> System;<br /><span style="color: #0000ff">using</span> System.Collections.Generic;<br /><span style="color: #0000ff">using</span> System.Linq;<br /><span style="color: #0000ff">using</span> System.Text;<br /><br /><span style="color: #0000ff">using</span> Microsoft.SpecExplorer.ObjectModel;<br /><br /><span style="color: #0000ff">namespace</span> TransitionSystemDemo<br />{<br />    <span style="color: #0000ff">class</span> Program<br />    {<br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)<br />        {<br />            <span style="color: #0000ff">if</span> (args.Length != 1)<br />            {<br />                Console.WriteLine(<span style="color: #006080">&quot;usage: transitionsystemdemo &lt;pathtoseexpl&gt;&quot;</span>);<br />                Environment.Exit(1);<br />            }<br />            <span style="color: #0000ff">try</span><br />            {<br />                var loader = <span style="color: #0000ff">new</span> ExplorationResultLoader(args[0]);<br />                TransitionSystem tsys = loader.LoadTransitionSystem();<br />                Process(tsys);<br />            }<br />            <span style="color: #0000ff">catch</span> (Exception e)<br />            {<br />                Console.WriteLine(<span style="color: #006080">&quot;failed: &quot;</span> + e.Message);<br />                Environment.Exit(2);<br />            }<br />        }<br /><br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Process(TransitionSystem tsys)<br />        {<br />            PrintStatistics(tsys);<br />            PrintPatterns(tsys);          <br />        }<br /><br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> PrintStatistics(TransitionSystem tsys)<br />        {<br />            Console.WriteLine(<span style="color: #006080">&quot;{0} states ({1} initial), {2} steps&quot;</span>,<br />                tsys.States.Length, tsys.InitialStates.Length, tsys.Transitions.Length);<br />            var captured =<br />                tsys.Transitions.Aggregate(<br />                        <span style="color: #0000ff">new</span> <span style="color: #0000ff">string</span>[0] <span style="color: #0000ff">as</span> IEnumerable&lt;<span style="color: #0000ff">string</span>&gt;,<br />                        (cs, tr) =&gt; cs.Concat(tr.CapturedRequirements).Concat(tr.AssumeCapturedRequirements))<br />                        .Distinct()<br />                        .OrderBy(x =&gt; x);<br />            Console.WriteLine(<span style="color: #006080">&quot;captured: &quot;</span>);<br />            <span style="color: #0000ff">foreach</span> (var req <span style="color: #0000ff">in</span> captured)<br />                Console.WriteLine(<span style="color: #006080">&quot;  &quot;</span> + req);<br />        }<br /><br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> PrintPatterns(TransitionSystem tsys)<br />        {<br />            <span style="color: #0000ff">foreach</span> (var stateLabel <span style="color: #0000ff">in</span> tsys.InitialStates)<br />            {<br />                Console.WriteLine(<span style="color: #006080">&quot;Starting in state {0}:&quot;</span>, stateLabel);<br />                Console.WriteLine(ToPattern(tsys, <span style="color: #0000ff">new</span> HashSet&lt;State&gt;(), GetState(tsys, stateLabel)));<br />            }<br />        }<br /><br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> ToPattern(TransitionSystem tsys, HashSet&lt;State&gt; visiting, State state)<br />        {<br />            <span style="color: #0000ff">if</span> (state.RepresentativeState != <span style="color: #0000ff">null</span>)<br />                <span style="color: #008000">// skip intermediate state</span><br />              <span style="color: #0000ff">return</span> ToPattern(tsys, visiting, GetState(tsys, state.RepresentativeState));<br />            <span style="color: #0000ff">if</span> (visiting.Contains(state))<br />                <span style="color: #008000">// Stop at cycle</span><br />                <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;&quot;</span>;<br />            visiting.Add(state);<br />            <span style="color: #008000">// compute successor</span><br />            var successors = GetSuccessors(tsys, state).Select(tr =&gt; ToPattern(tsys, visiting, tr)).ToArray();<br />            visiting.Remove(state);<br />            <span style="color: #0000ff">if</span> (successors.Length == 0)<br />                <span style="color: #008000">// end state</span><br />                <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;&quot;</span>;<br />            <span style="color: #0000ff">else</span> <span style="color: #0000ff">if</span> (successors.Length == 1)<br />                <span style="color: #0000ff">return</span> successors[0];<br />            <span style="color: #0000ff">else</span><br />                <span style="color: #0000ff">return</span> <span style="color: #006080">&quot;(&quot;</span> + <span style="color: #0000ff">string</span>.Join(<span style="color: #006080">&quot;|\r\n&quot;</span>, successors) + <span style="color: #006080">&quot;)&quot;</span>;<br />        }<br /><br />        <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> ToPattern(TransitionSystem tsys, HashSet&lt;State&gt; visiting, Transition tr)<br />        {<br />            var continuation = ToPattern(tsys, visiting, GetState(tsys, tr.Target));<br />            <span style="color: #0000ff">if</span> (continuation != <span style="color: #006080">&quot;&quot;</span>)<br />                <span style="color: #0000ff">return</span> tr.Action.Text + <span style="color: #006080">&quot;;\r\n&quot;</span> + continuation;<br />            <span style="color: #0000ff">else</span><br />                <span style="color: #0000ff">return</span> tr.Action.Text;<br />        }<br /><br />        <span style="color: #0000ff">static</span> State GetState(TransitionSystem tsys, <span style="color: #0000ff">string</span> stateLabel)<br />        {<br />            <span style="color: #0000ff">return</span> tsys.States.First(state =&gt; state.Label == stateLabel);<br />        }<br /><br />        <span style="color: #0000ff">static</span> IEnumerable&lt;Transition&gt; GetSuccessors(TransitionSystem tsys, State state)<br />        {<br />            <span style="color: #0000ff">return</span> tsys.Transitions.Where(tr =&gt; tr.Source == state.Label);<br />        }<br /><br />    }<br />}<br /></pre>

  <br /></div>]]></content:encoded>
    </item>
    <item>
      <title>静态模型与实例模型</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/93</link>
      <pubDate>Tue, 22 Dec 2009 06:49:14 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2009/12/22/93/</guid>
      <description><![CDATA[很多使用者问到什么时候选择静态模型，什么时候选择实例模型。  Spec Explorer的基础解决方案向导（Visual Studio...]]></description>
      <content:encoded><![CDATA[<p>很多使用者问到什么时候选择静态模型，什么时候选择实例模型。</p>  <p>Spec Explorer的基础解决方案向导（Visual Studio File菜单-&gt;New-&gt;Project-&gt;Visual C#-&gt;Spec Explorer Base Solution）在第二步对几种模型进行了简述，并让用户进行选择：</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/852bf574a5bf_C872/image_2%5B1%5D_2.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/852bf574a5bf_C872/image_2%5B1%5D_2.png"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="image_2[1]" border="0" alt="image_2[1]" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/852bf574a5bf_C872/image_2%5B1%5D_thumb.png" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/852bf574a5bf_C872/image_2%5B1%5D_thumb.png" width="357" height="276" /></a></p>  <p>所以在这里和大家探讨一下在什么情况下选择哪种模型。</p>  <p>大家可能还记得在之前的一篇博客中，我们讲到了两种连接测试用例与待测系统的方式：直接连接和适配器连接。如果你决定使用后者，那么适配器本身的设计决定了你选择静态模型还是实例模型。一个静态的适配器可以被用来控制一个基于实例的待测系统，反之亦然。考虑到测试适配器只是整个测试体系中的一个组件，所以这里进行选择的基本原理和设计任何一个面向对象的组件的基本原理是一致的。注意这里并不是一个是或者否的决定，静态和基于实例的Action可以共存于同一个适配器中。</p>  <p>Cord脚本中Action的声明被用于连接测试用例与待测系统或者适配器。总的来说，如果你的测试用例是调用待测系统或者适配器的静态方法，那么Action就应该是静态的；如果调用的是待测系统或者适配器的实例化方法，那么Action就是基于实例的。所以选择静态模型还是实例模型的决策权并不在建模者，而在于待测系统或者适配器的设计者。当然，两者可以是扮演不同角色的同一个人。</p>  <p>基于实例的Action意味着模型调用某一对象的方法，该对象不仅仅在模型探索阶段存在，在测试运行阶段也是存在的。所以该对象必须是之前某个步骤的输出，如果一个方法创建了一个没有返回的对象，那么显然这一对象不能在模型的后续步骤中被用到。</p>  <p>Spec Explorer允许把基于实例的Action与静态的模型方法进行对应（反过来亦可）。虽然一般来说不推荐这么做，因为基于实例的Action对应基于实例的模型方法，静态Action对应静态模型方法是很自然的设计，但是有时建模者不同意待测系统或适配器的设计，而希望用另一种模型设计。我们的目标是尽可能在满足需求的基础上让用户模型更为简单并更容易维护。</p>]]></content:encoded>
    </item>
    <item>
      <title>连接测试用例与待测系统</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/103</link>
      <pubDate>Tue, 22 Dec 2009 06:48:15 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2009/12/22/103/</guid>
      <description><![CDATA[Spec Explorer支持两种连接测试用例和待测系统的方式：直接连接和适配器连接。...]]></description>
      <content:encoded><![CDATA[<p>Spec Explorer支持两种连接测试用例和待测系统的方式：直接连接和适配器连接。 </p>  <p>直接连接是指将待测系统实现中的方法和事件直接声明成Cord配置中的Action（既可以依次声明也可以使用&quot;action all&quot;提取所有公用方法），这样生成的测试代码会直接调用待测系统的方法，并期待待测系统的事件。这种连接只能被运用于测试托管代码实现的系统，并且要求待测系统提供的API足够进行测试。</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/bfedb3be2037_C67E/direct_2.jpg" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/bfedb3be2037_C67E/direct_2.jpg"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="direct" border="0" alt="direct" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/bfedb3be2037_C67E/direct_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/bfedb3be2037_C67E/direct_thumb.jpg" width="354" height="247" /></a>&#160; </p>  <p>测试适配器是则是位于测试用例和待测系统之间的一层。当创建测试适配器时，Cord配置文件中的Action并不是待测系统的方法和事件，而是适配器中的方法与事件；那么生成的测试代码也调用适配器中的方法，期待适配器发起的事件。适配器的作用是把这些方法调用转换为待测系统的方法调用。当待测系统是非托管代码实现，或者测试用例与待测系统需要远程通信，或者存在一个中间层用于抽象模型和测试（比如控制待测系统的用户界面）时，这种连接被广泛运用。适配器由于避免了对托管测试代码的依赖，从而极大的增加了spec Explorer的适用范围。 </p>  <p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/bfedb3be2037_C67E/adapter_2.jpg" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/bfedb3be2037_C67E/adapter_2.jpg"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="adapter" border="0" alt="adapter" src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/sechina/WindowsLiveWriter/bfedb3be2037_C67E/adapter_thumb.jpg" original-url="https://blogs.msdn.com/blogfiles/sechina/WindowsLiveWriter/bfedb3be2037_C67E/adapter_thumb.jpg" width="358" height="254" /></a> </p>  <p>模型开发者与适配器或者待测系统的实现者基于Action的接口规范打成一致，即可并行工作。接口实现只要在需要运行生成的测试代码时能够执行即可。对于模型开发者来说，他们可以先把Action声明成abstract，即可在没有适配器或者待测系统实现的情况下进行建模。</p>]]></content:encoded>
    </item>
    <item>
      <title>Spec Explorer的历史</title>
      <link>https://docs.microsoft.com/archive/blogs/sechina/spec-explorer-3</link>
      <pubDate>Tue, 22 Dec 2009 06:43:28 GMT</pubDate>
      <dc:creator><![CDATA[Xiang Li]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/sechina/2009/12/22/spec-explorer-3/</guid>
      <description><![CDATA[Spec Explorer团队的架构师Wolfgang在自己的博客上有一篇关于Spec Explorer历史的文章，介绍了Spec...]]></description>
      <content:encoded><![CDATA[<p align="left">Spec Explorer团队的架构师Wolfgang在自己的博客上有一篇关于Spec Explorer历史的文章，介绍了Spec Explorer与Asml，Spec#，NModel等工具的关系。有兴趣的朋友可以<a href="https://blogs.msdn.com/wrwg/archive/2009/10/28/the-spec-explorer-story.aspx" target="_blank">浏览</a>一下。</p>]]></content:encoded>
    </item>
  </channel>
</rss>