响应式设计的自动化测试

响应式设计介绍

响应式设计(RWD)从2010年开始就逐渐进入人们的视线,虽然由于网速和网络的制约,目前国内都是采用针对pc和移动分别开发站点的策略,例如淘宝网的首页在pc端网页 ,在移动端的网页为网页,使用的是基于REM的布局设计。但是没人能否认响应式设计的重要性和简便性。响应式设计其实简单来说就是利用media query针对不同的设备和分辨率采用不同的css样式,用以达到网站在各个设备上的兼容性,再结合“移动优先”的策略,使得响应式设计更加的具有优势。如下图所示,就是一个简单的购物网站在不同设备上的响应式设计。

一个响应式设计的实现

下面就举一个简单的响应式网站的例子
代码见f2e-testing

  • 首页welcome页面
  • 登陆页面
  • notes列表页面
  • 新建note页面



公共头尾和菜单的响应式实现

这个属于很经典的响应式菜单和标题设计:
– 首页中如果是mobile或者ipad 则只显示标题的主要部分
– 菜单中如果是大屏,则一行显示菜单,mobile下用两行的菜单
– css完整实现:参见


<div id="header"> <div class="middle-wrapper"> <img id="header-logo" src="../src/assets/header-icon.png"> <h1> Sample Website <span class="not-on-mobile not-on-tablet">for Galen Framework</span></h1> </div> </div>
#menu {
    background: url("images/menu-background.png");
    margin: 0;
    color: white;
}
#menu ul {
    margin: 0;
    padding: 0;
    list-style: none;
}
#menu li {
    display: inline-block;
}
#menu ul:after {
    clear: both;
}
#menu li a {
    min-width: 100px;
    font-size: 1.2em;
    color: white;
    padding: 20px;
    display: inline-block;
}

@media (max-width: 500px) {
    .not-on-mobile {
        display: none;
    }

    #menu {
        width: 100%;
    }
    #menu li {
        width: 49%;
    }
    #menu li a {
        width: 100%;
    }
}
@media (max-width: 800px) {
    .not-on-tablet {
        display: none;
    }
}

welcome页面

welcome页面:使用的是bootstrap的jumbotron的布局,这款响应式布局
主要用在simple marketing or informational website。它具有一个通知的大型“布告栏”(jumbotron)和三栏式布局。
主要的实现代码:

    <div class="middle-wrapper">
        <div id="content">
            <div id="welcome-page" class="jumbotron">
                <h1>Welcome to our test page!</h1>

                <p>This app is used as a playground for <a href="http://galenframework.com/">Galen Framework</a></p>

                <p>
                    <button class="btn btn-lg btn-primary button-login" type="button" onclick="App.showLoginPage();">
                        Login
                    </button>
                </p>
                <p>To log in this website use the email <b>testuser@example.com</b> and password <b>test123</b>
                </p></div>
        </div>
    </div>

.jumbotron { padding: 30px; margin-bottom: 30px; color: inherit; background-color: #eee; } .jumbotron h1, .jumbotron .h1 { color: inherit; } .jumbotron p { margin-bottom: 15px; font-size: 21px; font-weight: 200; } .container .jumbotron { border-radius: 6px; } .jumbotron .container { max-width: 100%; } //大于768px @media screen and (min-width: 768px) { .jumbotron { padding-top: 48px; padding-bottom: 48px; } .container .jumbotron { padding-right: 60px; padding-left: 60px; } .jumbotron h1, .jumbotron .h1 { font-size: 63px; } } @media (max-width: 500px) { button { width: 100%; margin-top: 10px; } }

login登陆页面


@media (min-width: 501px) {
    .dialog-panel {
        width: 400px;
        border: 1px solid #ccc;
        padding: 20px;
        margin: auto;
        border-radius: 10px;
        box-shadow: 1px 3px 3px #ddd;
    }
}

响应式兼容尺寸

  • 合理的使用viewport

<meta name="viewport" content="width=device-width, initial-scale=1"> <!--或者使用如下的 --> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  • 使用hack兼容低版本浏览器的media query

<!-- HTML5 Shim and Respond.js IE8 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/libs/html5shiv/3.7.0/html5shiv.js"></script> <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> <![endif]-->
  • 参考bootstrap 3 它优先使用“移动优先”原则,详情:参考
    • Extra small devices ~ Phones (< 768px) col-xs-
    • Small devices ~ Tablets (>= 768px) col-sm-
    • Medium devices ~ Desktops (>= 992px) col-md-
    • Large devices ~ Desktops (>= 1200px) col-lg-

/*========== Mobile First Method ==========*/ /* RWD is – Desktop -> Tablet -> Mobile */ /* Mobile First RWD is – Mobile -> Tablet -> Desktop */ /* Custom, iPhone Retina */ @media only screen and (min-width : 320px) { } /* Extra Small Devices, Phones */ @media only screen and (min-width : 480px) { } /* Small Devices, Tablets */ @media only screen and (min-width : 768px) { } /* Medium Devices, Desktops */ @media only screen and (min-width : 992px) { } /* Large Devices, Wide Screens */ @media only screen and (min-width : 1200px) { } /*========== Non-Mobile First Method ==========*/ /* Large Devices, Wide Screens */ @media only screen and (max-width : 1200px) { } /* Medium Devices, Desktops */ @media only screen and (max-width : 992px) { } /* Small Devices, Tablets */ @media only screen and (max-width : 768px) { } /* Extra Small Devices, Phones */ @media only screen and (max-width : 480px) { } /* Custom, iPhone Retina */ @media only screen and (max-width : 320px) { }

响应式设计的自动化测试框架 – galenframework

介绍

  • 用于响应式设计的开源UI自动化测试框架
  • 测试spec “语义化友好”,通过位置信息准确定位各个元素的位置
  • 测试用例API兼容java和javascript
  • pc端和无线端多尺寸兼容,支持selenium appium saucelab browserstack多服务器测试
  • 可自定义输出的测试 html report

安装

  • 下载二进制代码
  • 执行 ./install.sh
  • galen -v 显示如下命令行 表明安装成功
Galen Framework
Version: 2.1.2
JavaScript executor: Rhino 1.7 release 5 2015 01 29

测试环境建立

  • 执行 galen config:生成config文件用于配置初始化文件,具体参数配置 详情参见
  • 文件结构
    • tests文件夹:用于装载测试脚本
      • init.js: 用于配置测试的设备和尺寸
      • pages文件夹: ui自动化测试的Page Object页面
      • login.page.test.js(默认是以.test.js后缀作为测试文件,如果有特殊要求可以在config文件中配置)
    • specs文件夹: 用于装载响应式设计的规则spec文件
      • common.spec文件:
      • loginPage.spec文件等等
    • config文件:配置文件
    • reports目录:用于生成自动化测试的html结果

构建测试服务

  • appium作为mobile的测试服务器,android真机测试的服务搭建,参考
  • selenium作为pc端的测试服务器
#server端:8002端口启动三星galaxy SIII设备的测试服务器;8001端口启动IPAD模拟器;启动chromepc端的测试服务器
node . -a 127.0.0.1 -p 8002 -U 4df752b06833bfd3 --browser-name Chrome --no-reset
node . -a 127.0.0.1 -p 8001 --command-timeout 50000  --no-reset
selenium-standalone start

#客户端:测试 并且测试完成后浏览器打开测试结果

Galen的命令行运行,参考

  • galen check:运行spec
  • galen test: 运行测试用例
  • galen dump:生成可视化spec-
galen test mytest01.test
    --htmlreport "htmlreport-dir"
    --testngreport "report/testng.xml"
    --jsonreport "jsonreport-dir"
    --parallel-tests 4

galen test tests/ --htmlreport reports   

galen check homepage.gspec
    --url "http://example.com"
    --size "640x480"
    --javascript "some.js"
    --include "mobile,all"
    --exclude "toexclude"
    --htmlreport "htmlreport-dir"
    --testngreport "report/testng.xml"
    --jsonreport "jsonreport-dir"

galen dump "specs/homepage.gspec"
    --url "http://galenframework.com"
    --size "1024x768"
    --export "dumps/homepage-dump" 
    --max-width "200" 
    --max-height "200"    

测试流程

createGridDriver建立对服务器的链接,并启动driver


var driver = createGridDriver('http://127.0.0.1:8001/wd/hub',{ desiredCapabilities: { browserName: 'Safari', 'platformVersion': '9.1', 'platformName': 'iOS', 'app': 'safari', deviceName:"iPad Air", size: '600x800', safariInitialUrl: 'about:blank' } }); driver.get("http://test.xxxxx.com");

checkLayout连接spec文件和.test.js测试文件

  • 编写测试脚本
  • 编写spec文件

检查spec文件是否符合预期

//定义test
test("Simplest test", function () {
    // here goes a test code
});

//[] spec中 @on的tag名称
checkLayout(driver, "specs/welcomePage.spec", ['desktop']);

使用 Page Object Model

PageObject在selenium中是常见的设计模式,它可以快速的将测试用例和测试主体相互分开,通过复用,减少代码;同时可以把测试过程变化的参数在统一的地方配置,减少改动的成本。关于 Page Object我会再开文介绍,这里只为大家介绍在galenframework中我们可以如何快捷的定义我们的PageObject,以登陆页为参考:

$page(pageName, primaryFields, [ secondaryFields ])

this.LoginPage = $page("Login page", {
  email: "input.email", // css locator
  password: "xpath: //input[@class='password']", // xpath locator
  submitButton: "id: submit", // id locator

  load: function () {
    this.open("http://example.com/login");
    return this.waitForIt();
  },
  loginAs: function (userName, password) {
    this.email.typeText(userName);
    this.password.typeText(password);
    this.submitButton.click();
  }
});
// now you can use it like this
var loginPage = new LoginPage(driver).load();
loginPage.loginAs("testuser@example.com", "password");

页面的webdriver操作函数

参考 GalenPage.js

  • 针对于$page这个对象
    • open 打开页面
    • waitForIt 等到primaryFields的元素都
    • wait({}).untilAll({}); 等
    • getAllLocators:把
    • findChild 定位元素
    • findChildren 批量定位元素
  • 针对pageElement(primaryFields还有secondaryFields中的元素)
    • attribute 获取属性
    • cssValue 获得css属性值
    • typeText input输入内容
    • click 点击按钮
    • clear 清空input
    • getText 获得输入的内容
    • hover
    • getWebElement
    • findChild
    • findChildren
    • isDisplayed 元素是否展现

操作并输出到report中

  • logged(text, callback)
  • loggedFunction(textExpression, callback)

//${_1} ${_2} 代表arguments loggedFunction("Log-in as ${_1} with password ${_2}", function (email, password) { this.emailTextfield.typeText(email); this.passwordTextfield.typeText(password); this.submitButton.click(); });

spec文件编写

spec文件是用于描述元素css之间的各种关系,符合语义化的要求,详情 参考

  • 定义Objects:@objects
  • tags和sections:= Main section =
  • 变量 @set
  • import其他的spec文件规则:@import header.spec
  • forEach Loop:循环
  • near – checks that object is located near another object
  • below – checks that an element is located below other object
  • above – checks that an element is located above other object
  • left-of and right-of – checks that an element is located above other object
  • inside – checks that object is located inside another object
  • width – checks the width of object
  • height – checks the height of object
  • aligned – checks horizontal or vertical alignment of object with other objects on page
  • text – checks the text that is visible on page
    • text is – checks that text is exactly as expected
    • text contains -checks element contains expected text
    • text starts – element should start with expected text
    • text ends – element should end with expected text
    • text matches – verifies that text matches Java Regular Expression
  • centered – checks that object is centered inside another object
  • absent – checks that object is either missing on page or is not visible
  • contains – checks that object visually contains other objects inside it
  • on – checks that object is visually located on other object
  • component – runs a subset of specs from another file within the given object context
  • color-scheme – checks the color distribution in the given object area


@objects search-panel id search-bar search-panel-input xpath //div[@id='search-bar']/input[@type='text'] search-panel-button css #search-bar a menu-item-* css #menu li a = Main section = @on * menu: height 70px @on mobile login-button: width 100px @on mobile, desktop menu: height 300 px @set commonHeaderMargin 10 to 20px contentMargin ~ 20px # Approximate = Header = header-icon: inside header ${commonHeaderMargin} top left textfield: near button 5 to 15px left # By top edge menu-item-1: aligned horizontally top menu-item-2 # iframe中定义spec @objects banner-frame css iframe#banner = Main section = banner-frame: component frame banner.spec # color scheme login-form: color-scheme 10% white, 4 to 5 % black, < 30% #f845b7 # image menu-item-1: image file imgs/menu-item-1.png, error 4%, tolerance 80 # 循环 = Main section = @forEach [menu-item-*] as itemName, prev as previousItem ${itemName}: right-of ${previousItem} 10px @for [ 1, 2 ] as index menu-item-${index}: above menu-item-${index + 2} 0 to 5px

完整的例子



mobile H5布局大全-rem flexbox详解

现在无线端的开发如火如荼,不同于国外网站经常做的响应式设计,国内很多大型网站都会专门实现基于H5的手机端mobile站点代码,淘宝、天猫、京东、百度等等,大抵是为了尽可能的减少设计和代码维护成本,也可能是为了实现代码的最小化减少请求代码量,虽然个人还是更倾向于响应式设计,但了解一些具有“无线端前端”开发的知识也未尝不是件好事。说起无线端开发,布局应该是最最具代表性的专题之一,因为不考虑ie系列的兼容性,因此除了pc端常常使用的浮动、表格、百分比布局等等 ,rem和flexbox更是火热的无线端布局实现手段,下面我们就从最基本的概念css像素看起,彻底的了解无线端的布局~~

一、viewport和像素

物理像素、CSS像素、独立像素和devicePixelRatio

  • 物理像素 device pixel: 物理像素指显示设备上的物理像素点
  • CSS像素 css pixel: 指我们写页面时理解的那个像素单位px
  • 独立像素dp: (dips device independent pixels): DP用在Android上,PT用在Apple上
  • 衡量设备的物理像素密度 DPI 和 PPI
    • DPI 指 Dots Per Inch(dpi ldpi mdpi hdpi for android)
    • PPI指 Pixels Per Inch。
    • http://dpi.lv/
  • window.devicePixelRatio = 物理像素/dips(dp) 等效于ddpx
  • dppx : device pixel / css pixel;
  • 分辨率(Resolution):屏幕区域的宽高所占像素数
  • 设计师DPI指南

viewport和devicePixelRatio

  • meta viewport
    • width:sets the width of the layout view port to the indicated value. device-width
    • initial-scale: sets the initial zoom factor of the page and the width of the layout viewport.
    • minimum-scale: sets the minimum zoom level (how much the user can zoom out).
    • maximum-scale: sets the maximum zoom level (how much the user can zoom in).
    • user-scalable: prevents user zooming when set to no. This is evil and we will demonstratively ignore it.
  • 使用viewport和devicePixelRatio实现兼容retina屏幕的像素

  • devicePixelRatio测试:http://www.quirksmode.org/m/tests/widthtest_vpdevice.html

  • css中使用devicePixelRatio

    .css{
        background-image: url(img_1x.png);
    }
    
    /* 高清显示屏(设备像素比例大于等于2)使用2倍图  */
    @media only screen and (-webkit-min-device-pixel-ratio:2){
        .css{
            background-image: url(img_2x.png);
        }
    }
    
    /* 高清显示屏(设备像素比例大于等于3)使用3倍图  */
    @media only screen and (-webkit-min-device-pixel-ratio:3){
        .css{
            background-image: url(img_3x.png);
        }
    }
    

  • vh单位:相对于视口的高度。视口被均分为100单位的vh

二、REM布局

rem原理

  • 使用相对尺寸的一种,随着页面宽度的改变,html的font改变,控制页面用rem标记元素的尺寸
  • 相对于百分比布局,控制局部尺寸更加方便
  • 参考 淘宝无线首页

代码

  • 需要设置基准元素还有最大的字体元素(防止全屏)
  • 核心计算公式
    • 页面宽度:getBoundingClientRect还是width
    • htmlFont = min[pageWidth/(psdWidth/basicFont, maxFont)
  • text-size-adjust调整100%
  • html font size的设置 拼css完成 而不是document.documentElement.style.fontSize
  • 绑定处理 DOMContentLoaded load resize 从未设置viewport的网页进入重新设置一下 pageshow/load persisted(是否后退进入)

实战

无线团队的lib.flexible

  • 1 代码
  • 2 不同点
    • 为了快速兼容vh单位 将布局分为了100份
    • 根据dpr控制meta的值,这样可以保证分别处理不同dpr的样式,但是增加了开发复杂度

三、Flexbox盒模型

原理

版本

  • 2009: http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/
  • 2011: http://www.w3.org/TR/2011/WD-css3-flexbox-20110322/
  • 2015: http://www.w3.org/TR/2014/WD-css-flexbox-1-20140925/
  • display: -webkit-box;

  • display: -moz-box; //2009
  • display: -ms-flexbox;//2011
  • display: -webkit-flex;
  • display: flex; //now

‘APIS’

  • demo
  • flex type

    • display: inline-flex (make element inline-block)
    • display: flex (make element block)
  • direction
    • flex-direction:row row-reverse column column
    • box-orient:horizontal vertical
  • wrap
    • flex-wrap: nowrap | wrap(if not enough place will put content to the next row/column ) | wrap-reverse (should not use in mobile safari)
  • flex-flow(direction wrap)
    • flex-flow: row nowrap;
  • justify-content(horizontal distribution)
    • justify-content: flex-start | flex-end | center | space-between | space-around;(should not use in mobile safari)
    • horizontal center:

      -webkit-box-pack:center;
      -webkit-justify-content:center;
      -ms-flex-pack:center;
      justify-content:center;

  • align-items (vertical distribution)

    • align-items: flex-start | flex-end | center | baseline | stretch
    • https://developer.mozilla.org/en-US/docs/Web/CSS/align-items

      -webkit-box-align:center;
      -webkit-align-items:center;
      -ms-flex-align:center;
      align-items:center;

  • align-self

    • used for flex items to change its align-items
    • align-items used for flex container
  • flex-grow flex-shrink

兼容性

autoprefix工具

实战

四、常见布局-等分和居中

五、常见布局-图片布局

六、代码转化为模板建立解决方案

七、其他

测试新手段可以选择不同机型不同的ADT实现测试-虽然付费但是相当的赞~~~
browserstack

css3和动画-part1-变换

常年开发web后台系统,实在厌恶了做不完的需求、调不完的接口、和各种数据交互,所以闲暇之余开始了动画和游戏的学习,也算一种调剂。动画比游戏应用更为广泛,所以我们先从动画说起,这系列教程主要包括如下几篇文章:

  • css3和动画-part1 基础篇;css3动画基础和实例(有demo有真相 力求比w3cschool实用些)
  • css3和动画-part2 进阶篇;理论结合实际实现几个较为复杂但有意思的动画效果
  • css3和动画-part3 蛋疼篇;transform、matrix和贝塞尔曲线
  • javascript和动画-part1 姊妹篇;使用javascript完成动画
  • javascript和动画-part2 姊妹进阶篇;高性能js动画类库分析-snabbt和gsap

废话不说(此处省略XXXX个字),上来先总结一下动画的相关的知识,让大家有个大概的印象,然后再各个击破。css3动画有很多名词都比较相似,例如 transform transiton translate,参数用法也特别容易混,这里我主要按照我学习的线索作为提纲分块讲解,希望对大家有所帮助:

  • 实现各种变换效果的关键字:transform: translate opacity skew rotate…
  • 静到动的实现函数:transition和animation
  • 3D相关:translate3d perspective

变换

不谈代码,我们大概能想到的变换效果都有哪些呢?放大、缩小、旋转、显隐,上下左右移动, 扭曲等等。对于这些变换,css3为给我们提供了丰富的效果关键字,这篇文章主要谈论常用的、高效的变换。之所以说是高效的变换,其实主要是在渲染的过程中能够尽量减少浏览器Recalculate的变换效果,参见High Performance Animations。这些变换有:

  • Position:translate
  • Scale
  • Rotate
  • opacity

transform

这个是个非常重要的关键字,他的作用是,transform:需要变换的属性 不同属性直接用空格分隔,举例来说要实现 某一文字放大并向右平移50像素,代码为:

    -webkit-transform: scale(1.1) translate(50px, 0);
    -ms-transform: scale(1.1) translate(50px, 0);
    transform: scale(1.1) translate(50px, 0)

下面就具体讲讲,被transform的各种变换效果。

translate

如果要实现元素从某一位置变换到另一个位置的时候,我们可以使用top left进行变换, 也可以使用margin-left margin-top,但是,其实这些都是会触发浏览器的Recalculate,会让动画出现卡顿,实现效率也非常的低下,参考jsperf做的对比,也可以戳戳Paul Irish的文章。如果改用translate这个关键字就可以非常cheaply的实现动画效果。translate主要是用来改变元素坐标的一种变换。API为:

  • transform: translate(tx[, ty]) /* one or two
    values */
  • transform: translateX(tx)
  • transform: translateY(ty)

常见的场景就是使用translate实现轮播的效果,下面是轮播的最简单的一个demo实现:

See the Pen translate by zhangmeng (@zhangmeng712) on CodePen.


最核心的代码就是:

.card-list.second {
  -webkit-transform: translate(-540px, 0px);
  -ms-transform: translate(-540px, 0px);
  transform: translate(-540px, 0px);
}
	

Tips: 我们不是电脑,没法记得哪些需要前缀哪些不需要,这里推荐给大家一个工具,autoprefixer这个是在caniuse这个网站的基础上用来帮我们实现兼容的前缀的,我们可以只写最基本的,他自动会帮我们补全,在线地址

scale

scale如同它的英文含义一样,是用来把元素进行放大缩小的,它也是非常实用的,先看API:

  • transform: scale(sx[, sy]);
  • transform: scaleX(sx);
  • transform: scaleY(sy);

scale最常见的应用就是在鼠标hover的时候把图标进行放大,以表示选中状态,引起注意,如下面这个demo,这里也有个工具网站推荐shapeofcss,在这里面可以找到我们常见的形状的实现。例子中同时使用了webfontIcon,这个技术让前端彻底告别切图的时代。

See the Pen scale demo by zhangmeng (@zhangmeng712) on CodePen.

rotate

rotate是用于让元素旋转的效果。旋转效果常配合着3D的效果一起使用,实现空间化的效果;也经常配合animation实现loading spinner的效果,如下demo:

  • transform: rotate(angle); /* an , e.g., rotate(30deg) */
  • transform: rotateX(angle);
  • transform: rotateY(angle);

See the Pen simple loading spinner by zhangmeng (@zhangmeng712) on CodePen.

opacity

opacity的用途其实更加的广泛,不管是rotate也好scale也好,如果没有一些opacity的变化就会让变换十分的生硬。配合opacity和display的切换是会导致重排的。所以如果需要元素的隐藏显示,最好采用opacity来控制。opacity还常常和animation配合起来,用于实现fadeIn fadeOut等人性化的动画设计。注意 opacity虽然是一种效果,但是并不需要使用transform来控制。API非常简单: opacity:0.4,记得每次开一个新的项目都会有实现transparent全兼容的css的代码,在此也为大家提供一下,见CssTricks

.transparent_class {
  /* IE 8 */
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";

  /* IE 5-7 */
  filter: alpha(opacity=50);

  /* Netscape */
  -moz-opacity: 0.5;

  /* Safari 1.x */
  -khtml-opacity: 0.5;

  /* Good browsers */
  opacity: 0.5;
}

本来想一篇文章把“变换” “动画” 还有“3D效果”一起讲解,但发现要说的东西太多了,为了保证质量,拆分成了三篇,力求把动画的内容涵盖完全,敬请期待哦~

参考: