我正在寻找改进网站功能测试自动化过程的建议。这是我过去尝试过的。
我曾经使用WATIN进行测试项目。您可以有效地编写类似“单元测试”的内容,并使用WATIN自动化浏览器点击您的网站等。
当然,您需要运行一个站点。所以我让测试实际上将代码从我的web项目复制到本地目录,并在任何测试运行之前启动指向该目录的Web服务器。
这样,有人可以从我们的源代码控制中获取最新信息并运行我们的构建脚本,并查看所有测试的运行情况。他们也可以简单地从IDE运行所有测试。
我遇到的问题是我花了很多时间维护代码来设置测试环境而不是测试。更不用说由于所有复制而花了很长时间才能运行。此外,我需要测试各种场景,包括安装,这意味着我需要能够将数据库设置为各种初始状态。
我很好奇你已经做了什么来自动化功能测试来解决其中的一些问题并且仍然保持简单。
更详细信息 由于人们要求提供更多详细信息,请点击此处。我正在使用Visual Studio和Cassini(内置的Web服务器)运行ASP.NET。我的单元测试在MbUnit中运行(但这不是那么重要。可能是NUnit或XUnit.NET)。通常,我有一个单独的单元测试框架运行我所有的WATIN测试。在AssemblyLoad阶段,我启动Web服务器并在本地复制我的所有Web应用程序代码。
我对任何平台的解决方案感兴趣,但我可能需要更多关于每个东西的含义的描述。 :)
答案 0 :(得分:11)
菲尔,
自动化可能难以维护,但您使用自动化进行部署的次数越多,您就可以将其用于测试设置(反之亦然)。
坦率地说,当使用非生成的构建工具时,更容易发展自动化代码,将其分解并将其重构为特定的小功能单元 只是驱动静态编译的,预先计算的功能单元,就像NAnt和MSBuild一样。这就是许多像NAnt这样早期用户的人已经转移到Rake的原因之一。 Rake可以自由地将构建代码视为任何其他代码 - 以共同演化其内容和形状。使用Rake可以轻松快速地在自动化工件中获得相同的停滞效果,并且在Rake中编写脚本比使用NAnt或MSBuild更容易。
因此,你的斗争的某些部分固有地与工具联系在一起。为了保持自动化的合理性和维护性,您应该警惕像NAnt和MSBuild这样的静态构建工具所带来的障碍。
我建议你不要将你的测试环境引导装配加载。这是一种由内而外的耦合,只是为了简单方便。在从IDE或命令行运行测试之前,或者从交互式控制台(例如C#REPL)运行测试之前,执行构建环境的构建任务没有任何错误(并且可能一切正常) Mono项目,或来自IRB。
测试数据设置有时只是一个痛苦的屁股。必须要这样做。
您将需要一个可以调用的库来创建和清理数据库状态。您可以从测试代码中直接进行这些调用,但我个人倾向于避免这样做,因为测试数据或示例数据控制代码的使用不止一次。
我从HTTP驱动所有示例数据控件。我用专门用于控制样本数据的操作编写控制器,并通过Selenium发出GET以对抗这些操作。我使用它们来创建和清理数据。我可以将GET编写为这些操作以创建设置数据的常见场景,并且我可以将数据的特定值作为请求参数传递(或者如果需要,可以传递表单参数)。
我将这些控制器放在我通常称之为“test_support”的区域。
我部署网站的自动化不会部署test_support区域或其路由和映射。作为部署验证自动化的一部分,我确保test_support代码不在生产应用程序中。
我还使用test_support代码自动控制整个环境 - 用假货替换服务,关闭子系统以模拟故障和故障转移,激活或停用与这些方面无关的功能测试的身份验证和访问控制,等。
从Web控制Web应用程序的示例数据或测试数据有很大的次要价值:在演示应用程序时,或者在进行探索性测试时,您可以通过发布一些针对已知的数据来创建所需的数据方案(或者可测试的)test_support区域中的url。真正做出有纪律的努力,坚持宁静的路线和资源导向将真正得到回报。
这个功能自动化(包括测试,部署,演示等)还有很多,所以这些资源设计得越好,你在长长的大厅里维护它们的时间就越多,你的机会就越多。我会发现以不可预见但有益的方式利用它们。
例如,在网页的语义模型上编写域模型代码将有助于创建更易理解的测试代码并降低脆弱性。如果你做得好,你可以使用那些具有各种不同驱动程序的相同模型,这样你就可以在压力测试和负载测试以及功能测试中利用它们,以及从命令行使用它们作为探索工具。顺便说一句,当您使用静态语言时,如果不像驱动程序类型那样绑定驱动程序类型,则更容易做到这一点。有许多领先的测试思想家和实干家在Ruby中工作的原因,以及为什么Watir是用Ruby编写的。重用,组合和表达在Ruby中比C#测试代码更容易实现。但这是另一个故事。
让我们赶上并更多地谈论其他90%的东西:)
答案 1 :(得分:2)
我们在一个项目中使用了Plasma。它模拟正在处理的Web服务器 - 只需将其指向Web应用程序项目的根目录即可。
它非常稳定 - 没有复制文件或启动进程外服务器。
以下是使用Plasma的测试如何寻找我们......
[Test]
public void Can_log_in() {
AspNetResponse response = WebApp.ProcessRequest("/Login.aspx");
AspNetForm form = response.GetForm();
form["UserName"] = User.UserName;
form["Password"] = User.Password;
AspNetResponse loggedIn = WebApp.ProcessRequest(Button.Click(form, "LoginUser"));
Assert.IsTrue(loggedIn.IsRedirect());
AspNetResponse homePage = WebApp.ProcessRequest(loggedIn.GetRedirectUrl());
Assert.AreEqual(homePage.Status, 200);
}
所有“AspNetResponse”和“AspNetForm”类都包含在Plasma中。
答案 2 :(得分:1)
我们目前正在为asp.net mvc应用程序使用自动构建过程。
我们使用以下工具:
我们使用在构建代理上运行的msbuild脚本,该构建代理可以是任意数量的计算机。 msbuild脚本从svn获取最新版本的代码并构建它。
成功后,它会将工件部署到给定的计算机/文件夹,并在IIS中创建虚拟站点。
然后我们使用MSBuild contrib任务来运行sql脚本来安装数据库并加载数据,你也可以进行恢复。
成功之后我们开始进行nUnit测试。测试设置确保硒启动并运行,然后以与Watin相同的方式驱动硒测试。 Selenium有一个很好的测试记录器,可以输出到c#。
关于Selenium的好处是你可以驱动FF,Chorme和IE,而不是仅限于IE,这是我上次看到它时Watin的情况。您还可以使用Selenium使用Selenium Grid进行负载测试,因此您可以重复使用相同的测试。
成功后,msbuild会在svn中标记构建。 TeamCity有一个隔夜运行的作业,它将最新的标签部署到一个临时环境,供业务用户在第二天早上检查项目状态。
在以前的生活中,我们没有&n; msbuild脚本来完全管理环境(安装java,selenium等)但是这确实需要花费很多时间,所以我们假设每个构建代理都安装了这些脚本。我们将及时纳入这些任务。
答案 3 :(得分:1)
为什么需要复制代码? Ditch Cassini让Visual Studio为您创建一个虚拟目录。当Web应用程序发生变化时,开发者必须记得在运行Web测试之前构建。我们发现这不是什么大问题,特别是如果您在CI中运行Web测试。
数据是一项巨大的挑战。据我所知,你必须在不完美的选择之间做出选择。这是我们如何处理它。首先,我应该解释一下,我们正在使用大型复杂的遗留WebForms应用程序。另外我应该提一下,域代码不适合在测试项目中创建测试数据。
这给我们留下了几个选择。我们可以:(a)在构建下运行数据设置脚本,或(b)使用实际网站通过Web测试创建所有数据。选项(a)的问题在于测试在一定程度上与脚本相结合。考虑将Web测试代码与T-SQL同步,让我头脑发热。所以我们去了(b)。
(b)的一个好处是您的设置还验证了应用程序行为。问题是...... 时间。
理想情况下,测试应该是独立的,没有时间耦合(可以以任何顺序运行)并且不共享任何上下文(例如,通用测试数据)。处理此问题的常用方法是在每次测试时设置和拆除数据。仔细思考后,我们决定打破这个规则。
我们使用Gallio(MbUnit 3),它提供了一些支持我们策略的不错功能。首先,它允许您在夹具和测试级别指定执行顺序。我们有四个“设置”灯具,订购-4,-3,-2,-1。它们以指定的顺序运行,并且在所有“非设置”灯具之前运行,默认情况下,它们的顺序为0.
我们的网络测试项目仅依赖于构建脚本:一个众所周知的用户名/密码。这是我可以忍受的耦合。随着设置测试的运行,它们构建了一个“数据上下文”对象,其中包含以后在其他所有灯具中使用(但从未更改过)的数据标识符(公司,用户,供应商,客户等)。 (通过标识符,我不一定是指键。在大多数情况下,我们的Web UI不会公开唯一键。我们必须使用名称或其他代理来导航应用程序以获得真正的标识符。更多内容见下文。)
Gallio还允许您指定测试或夹具依赖于另一个测试或夹具。当先例失败时,将跳过依赖项。这可以通过防止“级联失败”来减少时间耦合的罪恶,这可能会引起很多混乱。
创建一次基线测试数据,而不是在每次测试之前,将速度提高很多。但是,设置测试仍可能需要10分钟才能运行。当我正在进行新的测试时,我想经常运行并重新运行它们。输入另一个很酷的Gallio功能:氛围。 Ambience是DB4的包装器,它提供了一种非常简单的方法来持久化对象。我们使用它来自动保存数据上下文。因此,只能在重建数据库之间运行一次设置测试。之后,您可以反复运行任何或所有其他灯具。
那么清理测试数据呢?我们不需要从一个已知的州开始吗?这是我们发现破坏的权宜之计。对我们有用的策略是对公司名称,用户名等使用长随机值。我们发现,在逻辑“数据空间”内保持测试运行并不是很困难进入其他数据。当然,我担心我花了几个小时追逐一个幻影失败的测试只是为了发现它是一些数据冲突。这是目前为我们工作的权衡。
我们正在使用Watin。我挺喜欢它的。成功的另一个关键是Scott Bellware所提到的。在我们创建测试时,我们正在构建UI的抽象模型。所以不要这样:
browser.TextField("ctl0_tab2_newNote").TypeText("foo");
您将在我们的测试中看到这一点:
User.NotesTab.NewNote.TypeText("foo");
这种方法有三个好处。首先,我们永远不会重复一个魔术弦。这大大降低了脆性。其次,测试更容易阅读和理解。最后,我们将大部分Watin框架隐藏在我们自己的抽象背后。在第二个示例中,只有TypeText是Watin方法。这将使框架更改时更容易更改。
希望这有帮助。
答案 4 :(得分:0)
使用maven在构建过程中构建集成测试阶段很困难,但并非不可能。发生的事情基本上是这样的:
对于预整合测试阶段 -
启动Jetty运行应用程序命中测试数据库。
这一步的困难实际上是设置码头 - 我们无法让它从战争中启动,所以我们实际上必须让码头拆开战争,然后运行服务器 - 但它的工作原理,以及是自动化的 - 您所要做的就是输入mvn -PintegrationTest(这是我们的集成测试配置文件名称),然后关闭它。
答案 5 :(得分:0)
你的意思是说在构建完成后自动开始测试? 您可以编写自动脚本,以便在构建成功编译时将构建文件复制到正常工作的IIS。然后通过调用mstest.exe或其他方法启动自动BVT。
您可以尝试使用autoitx或某些函数语言,例如Python,ruby。