韶关网站建设:响应式界面设计的可视化测试驱动开发

2019.08.12 mf_web

123

测试响应式网站是一项艰巨的任务。到目前为止,为响应式布局的跨浏览器和跨设备测试实施稳定且可维护的自动化解决方案几乎是不可能的。但是如果我们有机会为响应式网站编写可视化测试呢?如果我们能够描述应用程序的外观并将其直接放入我们的测试中,该怎么办?

在考虑这个问题后,我决定再看一下视觉测试的另一个有趣的方面。很长一段时间以来,我一直是测试驱动开发(TDD)方法的粉丝。它帮助我完成日常编程工作。TDD使我能够正式确定任务并确保根据要求实施所有任务。

更重要的是,它帮助我在它们上线之前捕获了很多错误。在过去的七年中,我主要关注的是测试大型企业项目的自动化。随着时间的推移,我开始沉迷于使用TDD方法将自动化测试应用于响应式网站的外观和感觉。经过多年的研究,我想出了Galen框架 - 一种用于视觉测试的工具和特殊语言。这已经运行了一段时间,一旦语言变得足够成熟,我决定进行可视化测试驱动开发的实验。韶关网站建设

01-自适应设计-OPT

在本文中,我将详细描述此实验,并提出TDD作为前端开发的方法。我们将研究新的视觉测试技术,并研究如何充分利用它。

Galen框架简介

虽然是一项新技术,但Galen Framework已经被一些大公司使用,例如eBay,SkyScanner,Gumtree和Bestseller.nl,它也被用来测试华盛顿邮报的网站。除了企业公司,它还用于网络工作室,如ADCI Solutions。该框架是开源的,并在GitHub上托管,因此任何人都可以参与该项目并为代码做出贡献。

Galen Framework中的基本测试概念集中在检查所有页面元素相对于彼此的位置和大小。这样,您可以描述任何浏览器窗口大小的布局,而不必使用绝对定位。

使用Galen框架进行可视化测试的概念
使用Galen Framework进行可视化测试的概念(查看大图)

该盖伦规格语言的目的是要尽可能地类似于天然的英语,并已在半减价的方式来实现。那么,它看起来像什么?好吧,想象一下,你想检查一个“登录”按钮是否位于“取消”按钮旁边,并且右侧有一个10像素的边距,并且它们是水平对齐的。我们可以将该声明转换为Galen Specs:

login-button
  near: cancel-button 10px right
  aligned horizontally all: cancel-button

考虑另一个例子。如果我们想要检查徽标应该位于左上角的标题内,大约有20像素的边距,该怎么办?这是你如何做到的:

logo
  inside: header 17 to 22px top left

我们甚至可以使用快捷方式:

logo
  inside: header ~ 20 px top left

存在许多其他检查类型,所有这些类型都在官方文档中详细描述。学习曲线不是很陡峭。Galen Specs的结构非常简单,一旦你理解了它,测试就变得容易了。我们稍后会回到开头提到的实验,但首先让我先介绍一下TDD的整体情况。

测试驱动开发

TDD已经使用了很长时间,并且已经证明自己是构建可靠应用程序的强大方法。一开始,你可能觉得你在浪费时间编写测试,但是你将花费更少的时间来找到问题的根本原因。更重要的是,您可以专注于小型代码单元,并确保每个单元都具有良好的质量。测试数量将随主代码而增长,基本上,您将获得有关应用程序中任何问题的早期反馈。

视觉测试驱动开发的概念

那么,我们如何处理HTML和CSS的TDD呢?显然,它与传统的TDD略有不同,传统的TDD在白盒中实现测试。这就是为什么我添加“视觉”这个词,就像Galen框架一样:我们正在测试网站在浏览器中的呈现方式,我们并不特别关心它的内部结构。所以,这听起来更像是黑盒或灰盒测试。在本文中,我将向您展示如何在我们拥有任何页面之前首先编写布局测试来构建响应式Web页面。要记住的一件事是,我们的测试也将作为文档的来源,解释页面在任何设备上的外观。考虑到所有这些,让我们澄清这个过程。

  1. 设计和测试想象一下页面的外观。写一个草图,写一个测试。

  2. 代码实现HTML和CSS代码,并通过测试。

  3. 重构改进代码和测试。

基本的TDD方案
一个基本的TDD方案(查看大版本)

我们将把整个开发过程分解为小的迭代。另一个重要规则:对于每次迭代,我们将仅实现测试所需的代码。这样,我们将确保我们的测试覆盖率始终接近100%,并且我们不会被当前迭代中未声明的事物分散注意力。本文基于Workshop Shopping Cart的视觉TDD实验。它是一个GitHub项目,因此您可以跟踪其中的所有代码更改。

本实验

想象一下,我们已经决定建立一个购物车页面,我们希望它能够做出响应。该页面的功能与任何在线商店相同:用户应该能够查看他们的购物项目,继续付款或返回。

第1阶段:草拟的要求

我们坐下来思考所有细节,然后我们想出了这个草图:

初步设计草图
设计初步草图(查看大图)

现在看起来不错。如您所见,我们有三种类型的草图:桌面,平板电脑和移动设备。现在我们可以开始实施测试了。

阶段2:项目配置

对于本教程,我们不需要任何特殊的IDE - 任何文本编辑器都可以。这将非常简单。让我们创建我们的项目文件夹,shopping-cart并在其中创建两个文件夹:website和galen-tests。当然,配置本地Web服务器会更好,这样我们就可以http://localhost在测试中访问该页面。但由于我们只有一个页面,我们现在可以使用普通文件,通过file:///…URL 访问它们。

下载 Galen Framework并安装它。Galen Framework具有适用于Linux和Mac的安装脚本。如果您是Windows用户,请查看“ 为Windows配置Galen Framework ”。

创建我们上面讨论过的所有文件夹:

shopping-cart/
  |-- website/
  `-- galen-tests/

这就是现在。

阶段3.1:编写测试

让我们想一想如何将我们的工作分成小的迭代。我们首先想到的是构建一个基本页面骨架:

页面骨架草图
页面骨架草图(查看大图)

这意味着,目前我们在页面上只有五个对象:“标题”,“主要”,“导航”,“横幅面板”和“页脚”。让我们开始为我们的骨架编写Galen测试。在文件夹中galen-tests,创建另一个名为的文件夹specs。在其中,我们将保留所有Galen Spec文件。

让我们创建第一个galen-tests/specs/shopping-cart.spec,使用以下代码:

=====================================header          css #headernavigation      css #navigationmain            css #main-containerbanner-panel    css #banner-panelfooter          css #footer=====================================@ *--------------------header
  inside: screen 0px top left right  height: 60pxnavigation
  inside: screen 0px left  below: header 0pxfooter
  inside: screen 0px bottom left right  below: banner-panel 0px  height: 100px@ desktop------------------navigation
  width: 300px
  aligned horizontally all: main  near: main 0px leftmain
  below: header 0px@ desktop, tablet-------------------banner-panel
  below: header 0px  inside: screen 0px right  width: 300px  near: main 0px right
  aligned horizontally all: main@ tablet-----------------navigation
  inside: screen 0px left right  above: main 0px  width: 60pxmain
  inside: screen 0px left@ mobile----------------------navigation
  inside: screen 0px left right  above: main 0px  height: > 60pxmain
  inside: screen 0px left right  above: banner-panel 0pxbanner-panel
  inside: screen 0px left right  height: > 50px

正如您所看到的,我们已经在开始时定义了一些对象定位器,即使我们还没有任何HTML代码。这可能看起来有点奇怪,但另一方面它可能会变得有用。这样,我们必须预先考虑我们的DOM结构,并且我们已经可以提出一些关于如何构建HTML代码的好主意。例如,我们已经知道在我们未来的页面骨架中,我们将有一个<div id=“header”>…</div>元素和<div id=“footer”>…</div>。其他页面元素也是如此。如果由于任何原因我们决定更改DOM的结构,我们总是可以在一个地方更新我们的测试。

现在,我们还准备一个测试套件,它将执行三种尺寸的测试:台式机,平板电脑和移动设备。为简化起见,我们将通过调整浏览器窗口的大小来模拟移动或平板电脑布局。创建一个名为的文件galen-tests/shoppingCart.test并输入以下代码:

@@ table devices
  | device    | size     |
  | mobile    | 500x700  |
  | tablet    | 900x600  |
  | desktop   | 1300x700 |@@ parameterized using devicesShopping cart on ${device} device
  ${websiteUrl} ${size}
    check specs/shopping-cart.spec --include "${device}"

在上面的代码中,我们声明了一个devices包含三种屏幕尺寸设置的表。使用此表,盖伦框架将调用我们的测试三次,每次都不同device和size参数。我们还通过${websiteUrl}构造为网站的URL定义了占位符。我们稍后将从命令行提供此参数。

阶段3.2:编写代码

因为我们已经实现了初始测试代码,所以我们可以开始研究HTML和CSS。对于这个实验,我选择了Twitter Bootstrap。您可能认为Twitter Bootstrap已经过良好测试和响应。嗯,视觉TDD的目的是提出可靠的测试,并建立一个像素完美的网站。因此,用于构建网站的框架并不重要,因为最终Galen检查的唯一内容是屏幕上页面元素的位置。我选择Twitter Bootstrap只是为了简化实验,因为它已经有了我需要的东西,所以我不必浪费时间重新实现它们。尽管如此,我们对页面框架的Galen测试有严格的要求,我们需要根据这些要求提供页面。下载Twitter Bootstrap,并将其所有内容到该website文件夹中。在那里,我们应该有以下结构:

website/
  |-- css/
  | |-- bootstrap-theme.css
  | |-- bootstrap-theme.min.css
  | |-- bootstrap.css
  | `-- bootstrap.min.css
  |
  |-- fonts/
  `-- js/
    |-- bootstrap.js
    |-- bootstrap.min.js
    `-- npm.js

现在,我们实际上写一些HTML。使用以下代码创建在文件夹中命名shopping-cart.html的website文件:

<!DOCTYPE html><html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Galen Workshop - Shopping Cart</title>
    <!-- Bootstrap -->
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="main.css" rel="stylesheet">
    <!-- HTML5 shim and Respond.js for IE 8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="js/bootstrap.min.js"></script>
  </head>
  <body>
    <nav id="header" class="navbar" role="navigation">
      <div class="container-fluid">
        <div class="navbar-header">
          <h3>Header</h3>
        </div>
      </div>
    </nav>
    <div id="middle">
      <div class="row">
        <div id="navigation"
            class="col-xs-12 col-sm-12 col-md-2 col-lg-2">
          Navigation
        </div>
        <div id="main-container"
            class="col-xs-12 col-sm-8 col-md-7 col-lg-7">
          Main container
        </div>
        <div id="banner-panel"
            class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
          Banner panel
        </div>
      </div>
    </div>
    <div id="footer">
      <p>Footer</p>
    </div>
  </body></html>

使用以下内容创建main.css在我们的website文件夹中命名的文件:

#header {
  background: #2E849E;
  color: white;
  border-radius: 0;}#navigation {
  background: #faa;
  height: 100px;}#main-container {
  background: #afa;
  height: 100px;}#banner-panel {
  background: #aaf;
  height: 100px;}#footer {
  color: white;
  background: #222;
  height: 100px}

就是这样 - 我们完成了代码!您可能想要检查您所做的一切是否与GitHub存储库中的相同。现在我们可以运行测试并检查我们已经完成了这次迭代的一切。

阶段3.3:运行GALEN测试

因为我还没有配置本地Web服务器,所以我决定直接从我的本地文件系统进行测试。就我而言,如果我在浏览器中打开此页面,则URL将是file:///home/ishubin/workspace/workshop-shopping-cart/website/shopping-cart.html。所以,下面是我将如何将此URL传递给我们的测试:

galen test shoppingcart.test \-DwebsiteUrl="file:///home/ishubin/workspace/workshop-shopping-cart/website/shopping-cart.html" \--htmlreport reports

上面的命令将启动所有测试,并将在我指定的文件夹中生成HTML报告reports。如果您reports/report.html在浏览器中打开生成的文件,您应该看到以下图片:

报告概述
报告概述(查看大图)

如您所见,我们有一些失败。如果我们点击“桌面设备上的购物车”链接,我们会收到更详细的报告。

桌面测试的详细报告
桌面测试详细报告(查看大图)

正如您所看到的,部分的命名并不是那么漂亮。Galen默认使用标签名称。我们稍后会解决这个问题。我们来看看错误消息。有很多。让我们暂时关注第一次失败。如果单击它,您将获得屏幕截图,突出显示其上的元素。

布局失败的屏幕截图
布局失败的屏幕截图(查看大图)

我们得到的错误信息是“标题是15px而不是0px。”这是什么意思?注意标题和标题面板右边缘的错位?那就对了。此页面的问题是标题的宽度与视口匹配,但由于中间部分较大,因此增加了屏幕的大小。这也会在我们的页面上放置滚动条。而且因为我们最初向Galen说我们想要标题inside: screen 0px top left right,我们的意思是左边和右边不应有边距。但就是这样,所以这是一个错误。

让我们看看另一条错误消息,“导航是在标题下方20px而不是0px”。

布局失败的屏幕截图
布局失败的屏幕截图(查看大图)

最初在我们的规范文件中,我们声明导航面板应该是below: header 0px,这意味着它不应该从顶部有任何边距。但是在屏幕截图中我们清楚地看到了标题和中间部分之间的差距。同样,这是一个错误,我们必须解决它。

阶段4:修复失败的测试

我已经在带有v0.1.1标记的GitHub存储库中为它准备了一个修复程序。还有修复,我决定通过命名规范部分使测试提供更好的报告。

让我们先修复一下shopping-cart.html。这是更改的body元素:

<body>
  <nav id="header" class="navbar" role="navigation">
    <div class="container-fluid">
      <div class="navbar-header">
        Header
      </div>
    </div>
  </nav>
    <div id="middle" class="container-full">
      <div class="row">
        <div id="navigation"
           class="col-xs-12 col-sm-12 col-md-2 col-lg-2">
          Navigation
        </div>
        <div id="main-container"
           class="col-xs-12 col-sm-8 col-md-7 col-lg-7">
          Main container
        </div>
        <div id="banner-panel"
           class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
          Banner panel
        </div>
      </div>
    </div>
  <div id="footer" class="container-fluid">
    <p>Footer</p>
  </div></body>

现在让我们更新main.css文件:

#header {
  background: #2E849E;
  color: white;
  border-radius: 0;}.navbar {
  margin-bottom: 0;}#navigation {
  background: #faa;}#main-container {
  background: #afa;}#banner-panel {
  background: #aaf;}.container-full {
  margin 0 auto;
  width: 100%;}.row {
  margin: 0;}#footer {
  color: white;
  background: #222;
  height: 100px}

以下是对homepage.spec文件的更改。在这里,我为这些部分定义了专有名称。现在阅读测试会更容易。此外,一旦我们得到测试报告,它将被正确地结构化,这将使得更容易理解反馈。

=====================================
header          css #header
navigation      css #navigation
main            css #main-container
banner-panel    css #banner-panel
footer          css #footer
=====================================

@ Header | *
--------------------
header
  inside: screen 0px top left right
  height: 50px

@ Navigation | *
-------------------
navigation
  inside: screen 0px left
   below: header 0px

@^| desktop
-----------------------
navigation
  width: 200 to 350px
  aligned horizontally all: main
  near: main 0px left

@^| tablet
-----------------
navigation
  inside: screen 0px left right
  above: main 0px
  % height: 50 to 100px

@^| mobile
----------------------
navigation
  inside: screen 0px left right
  above: main 0px
  % height: > 60px

@ Footer | *
-------------------
footer
  % inside: screen 0px bottom left right
  below: banner-panel 0px
  height: 100px

@ Main | desktop
-----------------------
main, banner-panel
  below: header 0px

@^| tablet
----------
main
  inside: screen 0px left
  below: navigation 0px

@^| mobile
------------------
main
  inside: screen 0px left right
  above: banner-panel 0px

Let’s first fix our shopping-cart.html. Here is the changed body element:


<body>
  <nav id="header" class="navbar" role="navigation">
    <div class="container-fluid">
      <div class="navbar-header">
        Header
      </div>
    </div>
  </nav>
    <div id="middle" class="container-full">
      <div class="row">
        <div id="navigation"
           class="col-xs-12 col-sm-12 col-md-2 col-lg-2">
          Navigation
        </div>
        <div id="main-container"
           class="col-xs-12 col-sm-8 col-md-7 col-lg-7">
          Main container
        </div>
        <div id="banner-panel"
           class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
          Banner panel
        </div>
      </div>
    </div>
  <div id="footer" class="container-fluid">
    <p>Footer</p>
  </div>
</body>
And now let’s update the main.css file:
#header {
  background: #2E849E;
  color: white;
  border-radius: 0;}.navbar {
  margin-bottom: 0;}#navigation {
  background: #faa;}#main-container {
  background: #afa;}#banner-panel {
  background: #aaf;}.container-full {
  margin 0 auto;
  width: 100%;}.row {
  margin: 0;}#footer {
  color: white;
  background: #222;
  height: 100px}And below is the change to the homepage.spec file. Here I’ve defined proper names for the sections. Now reading the test will be easier. Also, once we get a test report, it will be properly structured, which will make it easier to understand the feedback.=====================================header          css #headernavigation      css #navigationmain            css #main-containerbanner-panel    css #banner-panelfooter          css #footer=====================================@ Header | *--------------------header
  inside: screen 0px top left right  height: 50px@ Navigation | *-------------------navigation
  inside: screen 0px left   below: header 0px@^| desktop-----------------------navigation
  width: 200 to 350px
  aligned horizontally all: main  near: main 0px left@^| tablet-----------------navigation
  inside: screen 0px left right  above: main 0px
  % height: 50 to 100px@^| mobile----------------------navigation
  inside: screen 0px left right  above: main 0px
  % height: > 60px@ Footer | *-------------------footer
  % inside: screen 0px bottom left right  below: banner-panel 0px  height: 100px@ Main | desktop-----------------------main, banner-panel  below: header 0px@^| tablet----------main
  inside: screen 0px left  below: navigation 0px@^| mobile------------------main
  inside: screen 0px left right  above: banner-panel 0px@ Banner panel | desktop, tablet-------------------banner-panel
  inside: screen 0px right  width: 220 to 400px  near: main 0px right
  aligned horizontally all: main@^| tablet--------------------banner-panel
  below: navigation 0px@^| mobile------------------banner-panel
  inside: screen 0px left right
  % height: > 50pxNotice the way we are defining our sections and tags now? The pipe symbol tells Galen to use the first part as a name of a section, while the second part (after the pipe) will be used for tag notation. Also, that weird syntax @^| tablet means that Galen should reuse the name from the previous section. We need this to be able to use a different tag for some objects in the same section. And because we don’t want to type the same section’s name multiple times, we can just use the ^ symbol.Another interesting feature is in this specification file. You may have noticed the % symbol in front of some checks. This tells Galen to ignore the failure and report it as a warning. I’ve declared this symbol for some checks because at the moment there is no content in the navigation, main or banner-panel sections. Once we add some content there, these warnings will go away and we can remove the symbol later.Now that we have the fix, let’s run our tests again. Remember the command we used the first time? Don’t forget to use your own path on your local machine.galen test shoppingcart.test \-DwebsiteUrl="file:///home/ishubin/workspace/workshop-shopping-cart/website/shopping-cart.html" \--htmlreport reportsOn my machine, all of the tests passed.Passed report overview (View large version)And here is the detailed report now that we have improved the naming of sections.Detailed test report (View large version)Now we can move on to the next iteration.Phase 5.10: Finish the ProjectDelivering a responsive page from my original sketch took me around 10 iterations. I won’t go over all of these iterations here because the process was the same: test, code, refactor. But you can track all of the progress on the workshop overview page. You can also view the shopping-cart page that I came up with in the end.Finished shopping-cart page (View large version)Of course, it still has some minor bugs in other browsers; I ran Galen tests only in Firefox. So, configuring the tests initially for real mobile devices along with all major desktop browsers might be a good idea. But the purpose of the experiment was just to try TDD for front-end development. That is why I didn’t focus on extensive cross-browser testing — although, to be honest, I think I should have. And if I had configured the website to be accessible from my Android phone and tablet, I could have used Appium with Galen Framework to test the layout.SummaryIt was an interesting experience. The way I worked in the past was to develop a website in one browser and then later hack it to work the same in other browsers. Fixing all of those nasty layout issues is really hard when you have a large HTML and CSS code base and a lot of third-party libraries — and especially if the website is supposed to be responsive. But applying TDD to front-end development helps a lot. It forces me to structure my code and my work process, and to focus on small things and deliver them at high quality.In the end, I get complete test coverage, which I can use for all regression testing. At some point, I might change some fonts, modify the layout of certain components or add some elements to the page. If something goes wrong, Galen will alert me right away. I encourage you to try this approach, too. It might help you in your website development.ResourcesGalen Framework“Shopping Cart: Visual Test-Driven Development” (workshop project), GitHub“Galen Sample Test,” GitHub A real JavaScript-based test project implementing Galen tests“Cross-Browser Layout Testing With Galen Framework and Sauce Labs,” Amber Kaplan, Sauce LabsImage Comparison for Layout Tests With Galen Framework (video tutorial), Ivan Shubin, YouTube“Galen,” Mind Engine Articles about Galen Framework(da, ml, al, il)

韶关网站建设

最新案例

联系电话 400-6065-301

留言