WebDriverAgent 简介

WebDriverAgent 是什么

去年的 SeleniumConf 上,Facebook 推出了一款新的iOS移动测试框架 —— WebDriverAgent,当时的推文上,写的还只支持模拟器。半年过过去了,如今在看官方github —— https://github.com/facebook/WebDriverAgent,已经宣称支持真机测试了(亲测的确支持)。我把它的 ReadMe 搬运过来:

WebDriverAgent 在 iOS 端实现了一个 WebDriver server ,借助这个 server 我们可以远程控制 iOS 设备。你可以启动、杀死应用,点击、滚动视图,或者确定页面展示是否正确。This makes it a perfect tool for application end-to-end testing or general purpose device automation.(它说它是iOS上一个完美的e2e的自动化解决方案) It works by linking XCTest.framework and calling Apple’s API to execute commands directly on a device.(链接XCTest.framework调用苹果的API直接在设备上执行命令) WebDriverAgent is developed and used at Facebook for end-to-end testing and is successfully adopted by Appium. (Appium封装工作正在进行中,如果一旦封装好,那么以后就可以直接用Appium提供的binding了。)It is currently maintained by Marek Cirkos and Mehdi Mulani.

8atmyHouse

这篇文章写于2013年03月15日,两年多过去了,我的愿望还是没有实现。最近看雪论坛的 Aker 猝死了,好好地散步就倒地身亡了。微信圈里转了个帖子,说腾讯游戏加班没天理,他们来年的愿望是晚上 8 点能准时下班,我感觉很惊讶,难道他们忘记了劳动法是8小时工作制吗?难怪人家说违法的事情来钱快。

Aker 之前,阿里云最近也挂了一个,也是站着猝死了。这年头猝死的人越来越多,现在只是耳闻,不知道什么时候就发生在身边或者自己身上。但是这些噩耗,似乎并没有什么卵用,就像大海里淹死只蚊子一般,波澜都没有。移动互联网时代,大跃进时代,拼命时代。升官发财请走别路,贪生怕死莫入此门。

说实在,每一次的死亡对我们都很伤,瞬间你就不知道自己坚持的事情到底对不对了。我看到知乎上,知乎侠们在喷各种加班——如何看待《腾讯互娱员工猝死,同事呼吁公司少加班》?。他们估计是在加班的时候讨论下加班。我们这样大一个群体,有着高学历,高智商的一个所谓精英群体,一起做着不合法,不合理的事情,然而没有任何一个人出来反抗,这是我感到最痛苦的。而另我更痛苦的是,我也是其中一员。

这大概真得是一条必经之路,社会到了这个需要各行各业都出来拼的阶段。安逸的生活从此不在。


我工作 6 年。 2 年徐汇, 2 年 黄浦, 2 年浦东。我住宝山区。我从一开始的愿望就是能踏着晨光上班,踩着夕阳下班。从来或者很少实现。有几次生病的下午,实在顶不住,请假回家,当地铁从地下穿入高空的时候,晴脆的阳光撒进车厢,我就想什么时候我可以不用朝九晚六。

8 at my house 说起来有段历史。2009 年,我外派在 Google DE 项目工作,8atmyHouse 就是这个项目的一个公用密码,很忙,每个人都希望晚上八点能到家。不知道别人怎样,反正我能刚刚好,想来在 google 上海的那段时间算得上是我职业生涯最快活的一段了。

离开之后,去了更远的张江集电港的 AMD, 每天 6 点出门,晚上 9 点到家。早上刮的干净的脸庞,晚上已胡子拉渣。除了感叹上海之大之外,也恨宝山怎么没有高科技。三个月之后实在受不了,投了几份简历之后,有幸去了稍微近一点的浦东南路的智涌。上班一个小半时,下班一个半小时,每天在跨越整个上海,从浦西到浦东,放在过去,就是每天去上海上班。

我到智涌后,也沿袭了 8atmyHouse 做密码的习惯。同事总会问,为什么用这个密码,我说希望八点能在家坐在沙发上看看电视看看书。他们又会问,能行么?我说看运气,如果永远踩着点,不落下任何一班车,那晚上8点半的时候,我可以坐在家里的电脑前。否则那八成还在回家的路上。同事问的多了,后来连老板也调侃我,比如最近夏令时了,是不是应该改成 7atmyHouse 。我其实想说这不是都靠老板你了么?

八点在家,说起来是多么容易的事情啊,这 6 年却有几次?也许再有猎头找我的时候,我一定告诉他,我要求不高,8 at my home!

Cucumber 和 Capybara 下的 PageObject

接上篇 由 step definition 失控引发的讨论和思考

PageObject

先来看下目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
.
├── Gemfile
├── Gemfile.lock
├── README
├── Rakefile
├── cucumber.yml
├── features
│   ├── example
│   │   ├── example.feature
│   │   ├── step_definitions
│   │   │   └── example_steps.rb
│   │   └── support
│   │   └── env.rb
│   └── blog_project
│   ├── user_management
| | |--- login.feature
| | |--- logout.feature
│   ├── post_management
| | |--- write_a_post.feature
│   ├── upload_image.feature
│   ├── pages
│   │   ├── login_page.rb
│   │   └── post_page.rb
│   ├── step_definitions
│   │   ├── post_step.rb
│   │   ├── user_step.rb
│   │   ├── common_steps.rb
│   └── support
│   ├── env.rb
│   └── helper
│   └── path.rb
└── features_report.html
  1. 把 features 按照模块用目录分类。
  2. 将 page object 放在 pages 目录下。
  3. 每一个模块一个 step definition rb 文件。
  4. 在 support 里配置各种环境啊,hook啊,帮助类等。

其实无论你怎么写, cucumber 运行的时候,都会把这些 rb 一股脑儿加载进来。所以对于
cucumber 来说什么样子的目录结构对它无所谓,所以对我们而言,只要方便管理就可以了。

现在我们就要在 pages 这个目录做文章。在 cucumber 下使用 pageobject 一般有两种方法:

1. 自己封装

自己封装 pageobject 的过程其实就是把 webdriver page object java 的那一套翻译成 ruby。

  • 提取页面元素
  • 封装页面业务逻辑

比如:

login_page.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class LoginPage
URL = "/login"
def initialize(session)
@session = session
end
def visit
@session.visit URL
end
def username_input_element
@session.find "input[name=username]"
end
def password_input_element
@session.find "input[name=password]"
end
def login name, password
username_input_element.type name
password_input_element.type password
@session.click_button("login")
end

login_stepdef.rb

1
2
3
4
5
6
7
8
Given /^I am in the home page$/ do
@login_page = LoginPage.new(Capybara.current_session)
@login_page.visit
end
When /^I login with usernmae "test" and password "test"$/ do |name, password|
@login_page.login name, password
end

2. 使用现成的 gem

ruby 界最不缺的就是第三方实现了。github 里一搜一大把。

我最早用的是 cheezy/page-object

>

  1. A Simple DSL you can use to define and interact with the content on your page
  2. Support for both watir-webdriver and selenium-webdriver
  3. An easy way of creating and using page objects in your cucumber steps or in rspec
  4. A Simple way of dealing with Frames and iFrames
  5. Robust way of dealing with Ajax Calls
  6. A clean way of handling Javascript Popups
  7. Support for most html Elements

使用非常简单:

login_page.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
class LoginPage
include PageObject
text_field(:username, :id => 'username')
text_field(:password, :id => 'password')
button(:login, :id => 'login')
def login_with(username, password)
self.username = username
self.password = password
login
end
end

login_stepdef.rb

1
2
3
4
5
6
7
8
Given /^I am in the home page$/ do
visit HOME_PATH
@login_page = LoginPage.new(Capybara.current_session)
end
When /^I login with usernmae "test" and password "test"$/ do |name, password|
@login_page.login_with name, password
end

具体可以移步:Get started!

说心里话,如果不是用 capybara 的话, 在 ruby 下写 webdriver 自动化,必然首选 cheezy/page-object

我们这次选择了 SitePrism

A Page Object Model DSL for Capybara
SitePrism gives you a simple, clean and semantic DSL
for describing your site using the Page Object Model pattern, for use with Capybara in automated acceptance testing.

在 cucumber 中使用 SitePrism 需要加入依赖

1
2
3
4
require 'capybara'
require 'capybara/cucumber'
require 'selenium-webdriver'
require 'site_prism'

其实只要在 Gemfile 中加入以下 gem 即可:

1
2
3
gem "cucumber-rails"
gem "capybara"
gem "site_prism", "~> 2.4"

使用同样非常简单:

login_page.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
class LoginPage < SitePrism::Page
set_url "/login"
element :username_input_field, "input[name='username']"
element :password_input_field, "input[name='password']"
element :login_button, "button[name='login']"
def login_with username, password
username_input_element.type username
password_input_element.type username
login_button.click
end
end

login_stepdef.rb

1
2
3
4
5
6
7
8
Given /^I am in the home page$/ do
@login_page = LoginPage.new # 不用传 driver 哦~
@login_page.load
end
When /^I login with usernmae "test" and password "test"$/ do |name, password|
@login_page.login_with name, password
end

Summary

可以看得出,page object 的方案还是很多的,自己定义比较灵活,轻巧,使用 gem 可以省去不少心思。
个人建议是,使用 gem, 如果gem 无法完成的,再上自己封装!

我想请你来听听蛙鸣声

以前看过一部台湾的电影,年轻人爱上了大自然的声音,拿着各种专业的录音设备,去海边,去森林,录潮汐声,录松树的声音,然后把卡带寄给心爱的女孩。

我很久没有听过那么齐整的蛙鸣,在晚风中,在西溪园区靠水的围栏边,我知道那一片黑暗是水和沼泽,蛙群鼓足勇气迎接夏天。我想打电话给顾吉辰,然后把手机贴向黑暗蛙鸣过来的地方,告诉她这边还有自然。

你好陌生人

我以前从没试过失那么久的眠,我以前从没试过出那么久的差,我以前从没试过出那么久的差的时候在旅馆失那么久的眠。我现在都试过了。

我把吹风机架在枕头上,我把刚洗的衣服挂在床沿上。我大学的时候干过这个事情。特别是放假回家前的晚上,大家都急着晒干衣服。每一个寝室的电扇上都会挂着条泛黄的内裤或者内衣。穿着裤衩的我们举着电吹风。

我在杭州读的大学,我一直想我大概再也没有机会干这事情了。我想的事情一直很不准。

我的朋友金金一直出差,我认识他快20多年,他有一半时间在出差,另一半时间在出差的路上。

出差是一种生活态度。有的人很惬意,有的人很苦恼。对我而言,就是偶尔想家和我的锦新和锦年。

10年的时候,我在北京出了一次差。金金从天津跑来看我,我们在新年旅舍没有窗户的房间睡了一晚,在大永和吃了早饭,然后他回去。我在谷歌大楼待了两天也回了上海。

对于宅男而言,永远想不到出去走走。我在杭州读书的时候,除了寝室最熟悉的就是食堂了。而校园以外,那不是宅男该去的。

07年夏天,我毕业,和发证书的老师大吵一架后,叫了辆残疾车,沿着西湖直奔火车站,扬长而去。从此,留在杭州的一切过往都是陌生人。

读冯唐

我在微博上@多看阅读,说上帝给了我多看,我却用它来看冯唐。多看没有回复我,我想她大概不好意思,我一直觉得客服是美眉。我有个同学家里网络不好,打电话给客服美眉,客服说你设置错了。我同学大怒,说我计算机博士,于是客服美眉就不好意思了,给他换了路由器。多看推出微信大号的时候说24小时人工服务,我回她说扯淡,明明机器人回复。结果她和我聊起来了,应该没有那么智能的机器人。同样是搞计算机的,本科和博士到底不一样。

我最近写文章变的矫情刻薄,我都怪冯唐。我老婆说你写的酸死了,像个屌丝。我说冯唐看多了,她说啥是冯唐?我说一屌丝。感觉还是没多少人知道冯唐,就像没多少人知道王小波写程序一样。我总觉得秋水是学计算机的,因为只有计算机,能出文艺屌丝。

秋水比我们大一个十年。他读到博士的时候,我们估计还在初中拿红领巾擦鼻涕。知识就是力量,这也是为什么我初一的时候打不过初三的流氓的原因。

所以我应该也打不过冯唐,好吃不过饺子,流氓不过冯唐。只有他那么自在地写着肉欲横流的青春。什么能让案板上的猪胸脯吸引人,给它按两个奶子。那样的年纪看完岛国片估计能红着眼到处物色奶子。

我一直想青春是什么,是年纪,是思想,还是身体?直到雨季来了,赵忠祥老师说,草原上的雄狮开始物色母狮。原来这才是青春。

我这才发现我不仅开始尖酸刻薄,我还满嘴污言秽语。我都怪冯唐。

[翻译]Android and iOS Support

简而言之:我们准备淘汰 Selenium 自己的 AndroidDriver 和 iPhoneDriver,改用 Selendroid,iosdriver 和 Appium中的任意一个。如果你正在使用 Selenium 的 mobile driver 中的一个的话,请评价下这些替代品。

正文:

在 2007 年, 乔布斯发布了 iPhone,从此移动web从本来的新奇事物走上了主流,成为大众的宠儿。如今的趋势预示着在不远的将来,移动 web 的使用将超过桌面应用的使用。移动 Web 将成为你站点重要一部分,而且在移动设备上测试你的网站将是一个明智的想法。而这在未来将会持续一段时间。

Selenium 项目通过实现 iOS 和 Android 版本的 webdriver 来回应崛起的移动 web。在2009年初期,我们加入了 iPhoneDriver (在 iPad 上也能工作)。2010年6月,最初由 Google 工程师开发的 AndroidDriver 也加入了阵营。 直到今天,你能在官方 Android SDK 的下载选项中发现 “Google WebDriver”的身影。

在最初的工作完成之后,一些有趣的事情发生了。在 Selenium 项目之外,坊间对这些移动 driver 做了很多实验性的扩展和修改。第一个就是“nativedriver”,我也参与于此。它采用了一个新奇的方式,使用熟悉的 WebDriver 接口,允许用户和手机(Android 或者 iOS)原生的 UI 交互。我第一次见到它时,惊呆了。但是开发它的工程师很快就向我证明了这是有意义的。你猜怎样,他们是对的。

可惜的是,在证明这个主意是可行且能工作后,NativeDriver 项目突然失去了动力。但是,它给其他三个项目做好了准备,这三个项目采用了它的理念,创造了非常棒的移动测试软件,他们就是: Selendroid, iosdriver 和 Appium。这三个项目都允许用户用熟知的 WebDriver 接口来测试iOS 和 Android 上的应用。不仅仅是原生的应用,也包括混合或者纯web的应用。最近 Windows Phone WebDriver 也加入了他们,我们可以用来测试 WinPhone 8 上的移动 web 应用。

这些项目都有一个共同点:他们比 Selenium 移动主项目更加地活跃,更能胜任移动测试工作,也已经走的更远。事实上,原先在 AndroidDriver 和 iPhoneDriver 上的贡献者也开始在这些项目上工作了。我们需要维护不同 driver 间的互通性,允许用户选择最适合他们的框架,而不必担心他们的测试会需要大量重构。

这就意味着在 selenium 项目中继续保留 AndroidDriver 和 iPhoneDriver 已经不能帮助用户了。那些替代者才是更好的选择。保留这些所谓官方的 driver 只会污染了项目。而且更糟糕的是,selenium 的开发修复这些 driver 上的 bug 非常慢,而这些 bug 让每个参与与此的人都非常沮丧。鉴于此,Selenium 项目决定删除这些driver的代码。我们推荐大家评估那些备选的其中之一使用。

当然,这些代码会仍然保留在我们的代码历史中,所以如果你想自己构建一个的话,还是有可能的。最新的 iPhoneDriver 是 ef9d578,最新的 AndroidDriver 代码是 00a3c7d。我们已经上传了最新版本的 AndroidDriver 供你下载。

这些改变并不意味着我们不再支持移动测试。它意味着我们只支持最好的 mobile WebDriver 实现,只是他们不是 Selenium 项目的一部分而已。

原文见 http://seleniumhq.wordpress.com/2013/12/24/android-and-ios-support/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+Selenium+%28The+Official+Selenium+Blog%29

游戏开发常用概念

zz from 守望者科技博客

游戏开发中,需要了解 概念,分别是导演、场景、布景和人物角色。这几个概念和拍电影相似,那么我们就拿电影和游戏做对比,一一讲解这几个概念。

  • 导演(在cocos2d-x引擎中与之对应的类事CCDirector)。游戏里,导演是游戏创作的组织者和领导者,是把游戏策划变成游戏的总指挥,导演制定规则让游戏内的场景、布景和人物角色有序地运行。
  • 场景(在cocos2d-x引擎中与之对应的类事CCScene)。场景是一个个的关卡,关卡主要有布景和人物角色组成。

  • 布景(在cocos2d-x引擎中与之对应的类事CClayer)。布景是每个关卡里面的背景,同样,不同的关卡需要的背景也是完全不一样的。

  • 人物角色(在cocos2d-x引擎中与之对应的类事CCSprite)。人物角色包括游戏的主玩家和其他玩家了。其他玩家既可以是一个真实的玩家,也可以是游戏虚拟出来的玩家。
  • 动作(在cocos2d-x引擎中与之对应的类事CCAction)。动作是游戏内人物角色的动作。
  • 摄像机(CCCamera),每个节点都需要使用摄像机,当节点发生缩放,旋转,和位置变化时,都需要覆盖摄像机,让这个节点通过摄像机重新渲染。

Cron jobs and random times, within giving hours

最近给 Dota 圣剑传说 添加一个随机活动,每小时里在聊天室生成一个 黄金巨龙来袭事件。从 stackoverflow 找来一个方法如下:

http://stackoverflow.com/questions/9049460/cron-jobs-and-random-times-within-giving-hours

If I understand what you’re looking for, you’ll need to do something a bit messy, like having a cron job that runs a bash script that randomizes the run times… Something like this:

crontab:

1
0 9 * * * /path/to/bashscript

and in /path/to/bashscript:

1
2
3
4
5
6
7
#!/bin/bash
maxdelay=$((14*60)) # 14 hours from 9am to 11pm, converted to minutes
for ((i=1; i<=20; i++)); do
delay=$(($RANDOM%maxdelay)) # pick an independent random delay for each of the 20 runs
(sleep $((delay*60)); /path/to/phpscript.php) & # background a subshell to wait, then run the php script
done

A few notes: this approach it a little wasteful of resources, as it fires off 20 background processes at 9am, each of which waits around for a random number of minutes (up to 14 hours, i.e. 11pm), then launches the php script and exits. Also, since it uses a random number of minutes (not seconds), the start times aren’t quite as random as they could be. But $RANDOM only goes up to 32,767, and there are 50,400 seconds between 9am and 11pm, it’d be a little more complicated to randomize the seconds as well. Finally, since the start times are random and independent of each other, it’s possible (but not very likely) that two or more instances of the script will be started simultaneously.

|