随着Android的快速演进,先后经历了 Android 测试框架从 InstrumentationTest, Robotium, Monkeyrunner, 直到 uiautomator 的变化,从目前来看,对于独立的QA团队来说,uiautomator 是最适合的 Android 测试框架.

就我个人的体会,沉重的 Java 语言及其繁琐的工具链,是阻碍 uiautomator 推广的障碍,个人更喜欢 Python 和 Javascript 的快速开发和方便的工具链。为了更方便地利用 uiautomator,花了两周时间实现了 Android uiautomator 的 Python Wrapper 模块并开源出来:

希望下一步能有时间完成相应的 nodejs 模块。

Ubuntu 提供了一个良好的 Python 开发环境,但如果想使我们的开发效率最大化,还需要进行很多定制化的安装和配置。下面的是我们团队开发人员推荐的一个安装和配置步骤,基于 Ubuntu 12.04 桌面版本标准安装。

安装 Python 发布版本和 build 依赖包

建议至少安装 Python 2.7/3.2 版本,毕竟 Python 2.X/3.X 还是有不少区别的。

1
2
3
4
# 安装 Python 发布版本,dev包必须安装,很多用pip安装包都需要编译
sudo apt-get install python2.7 python2.7-dev python3.2 python3.2-dev
# 很多pip安装的包都需要libssl和libevent编译环境
sudo apt-get install build-essential libssl-dev libevent-dev libjpeg-dev libxml2-dev libxslt-dev
Read on →

最近正在团队内部普及 Python 语言,有些刚接触 Python 语言的工程师在概念上有很多混淆的地方,刚好看到这篇文章:Python面试问题,里面列举的问题都是关于 Python 基本的常识或者容易混淆的知识点,因此推荐给团队的 Python 初学者。

Read on →

Python是很强力的编程语言,它即支持面向对象编程的特征,也支持很多函数式编程的特征,同时还是一门动态语言。由于Python语言特征的多样性,对于同一种设计需求,我们可以采用多种完全不同的方式进行实现。优秀的软件工程师总能在这些实现方式中,根据他们的优劣,选择出最适合的方式。

下面的内容源自StackOverflow的一篇文章:Creating a singleton in python

这个问题不是为了讨论单体实例是否是有必要的,或者是反面模式,也不是为了挑起任何宗教式的战争,而是为了讨论如何用更Pythonic的方式,最佳地实现单体实例模式。

Read on →

Markdown是网络书写语言,特别适合程序员书写文档:

  • 全文本格式,方便进行diffpatch和版本的管理;
  • 格式直观,简单易学,便于书写和阅读;
  • 兼容 HTML,能方便地转换为 pdf,doc等格式;
  • 支持 Linux,Windows,Mac;
  • 支持内嵌代码和语法高亮;

估计只是方便版本管理,就能吸引很多程序员的兴趣,特别是需要团队一起参与书写文档的时候。感兴趣的可以参考官方网站,或者以前写的一份使用 Markdown 的 slides

但是毕竟Markdown只是书写语言,不是程序设计语言,如果我们需要嵌入 UML 的时候,不可避免地需要其他专业软件的支持。这里介绍几种利用网络服务,可以直接在Markdown文档中嵌入的 UML 建模图:

Read on →

原文: Team Collaboration With GitHub


GitHub已经成为的一切开放源码软件的基石。开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目。除了​​代码托管,GitHub的主要吸引力是使用它作为一个协作开发工具。在本教程中,让我们来看看一些最有用的GitHub的功能,特别是使团队工作更有效率,更高生产力,非常重要的,好玩的那些功能!


GitHub和软件合作

有一件事我觉得非常有用的是,可以将GitHub的维基集成到项目的源代码主线上。

本教程假定您已经熟悉Git – 开放源码的分布式版本控制系统,由Linux的创世人Linus Torvalds在2005年创造的。如果您需要修改或查找有关Git,请访问我们以前的截屏教程,和一些文章。此外,你应该已经有一个Github上的帐户,并做了一些基本的功能,如创建一个存储库,并推送到GitHub上。如果没有,可以参照更多以前的教程

在这个世界上的软件项目,不可避免的是,我们必须和一个团队一起工作来交付软件。在本教程中,我们将探索一些软件开发团队最常用的工具。这些工具包括:

  • 添加团队成员 – 组织和合作者
  • Pull请求 – 发送代码变更和合并
  • 问题跟踪 – Github上的错误记录
  • 分析 – 图形与网络
  • 项目管理TrelloPivotal Tracker
  • 持续集成Travis CI
  • 代码审查 – 代码行评论与URL查询
  • 文档记录 – Wiki与Hubot

更喜欢截屏操作视频?

如果你倾向于观看截屏操作视频,可以观看下面的截屏操作视频,而将本教程作为旁注。

Read on →

什么是 DropBoxManager ?

Enqueues chunks of data (from various sources – application crashes, kernel log records, etc.). The queue is size bounded and will drop old data if the enqueued data exceeds the maximum size. You can think of this as a persistent, system-wide, blob-oriented “logcat”.

DropBoxManager 是 Android 在 Froyo(API level 8) 引入的用来持续化存储系统数据的机制, 主要用于记录 Android 运行过程中, 内核, 系统进程, 用户进程等出现严重问题时的 log, 可以认为这是一个可持续存储的系统级别的 logcat.

我们可以通过用参数 DROPBOX_SERVICE 调用 getSystemService(String) 来获得这个服务, 并查询出所有存储在 DropBoxManager 里的系统错误记录.

Android 缺省能记录哪些系统错误 ?

我没有在官方的网站上找到关于哪些系统错误会被记录到 DropBoxManager 中的文档, 但我们可以查看源代码来找到相关信息. 从源代码中可以查找到记录到 DropBoxManager 中各种 tag(类似于 logcat 的 tag).

crash (应用程序强制关闭, Force Close)

当Java层遇到未被 catch 的例外时, ActivityManagerService 会记录一次 crash 到 DropBoxManager中, 并弹出 Force Close 对话框提示用户.

ActivityManagerServicelink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
    ProcessRecord r = findAppProcess(app, "Crash");
    final String processName = app == null ? "system_server"
            : (r == null ? "unknown" : r.processName);

    EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
            UserHandle.getUserId(Binder.getCallingUid()), processName,
            r == null ? -1 : r.info.flags,
            crashInfo.exceptionClassName,
            crashInfo.exceptionMessage,
            crashInfo.throwFileName,
            crashInfo.throwLineNumber);

    addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);

    crashApplication(r, crashInfo);
}
Read on →

Grunt 是一个非常优秀的 Javascript 构建工具, 虽然它的 Build-in 的任务非常有限, 但是它提供了一套非常灵活的插件机制, 可以进行任务扩展. 目前在官网上的第三方任务插件数目已经达到 160+, 并且在持续增长中… 对于通用的功能基本上都能找到对应的任务插件, 当然你也可以自己写扩展任务来满足特殊的构建需求.

我通常会直接使用 bbb, 因为 bbb 已经收集齐了我想用到的任务插件, 非常顺手.

对我而言 bbb 已经足够用了, 尽管这样, 在第一次尝试 Yeoman 之后, 我还是忍不住想向大家推荐这个新的工具.

Yeoman is a robust and opinionated client-side stack, comprised of tools and frameworks that can help developers quickly build beautiful web applications. We take care of providing everything needed to get started without any of the normal headaches associated with a manual setup.
With a modular architecture that can scale out of the box, we leverage the success and lessons learned from several open-source communities to ensure the stack developers use is as intelligent as possible.
As firm believers in good documentation and well thought out build processes, Yeoman includes support for linting, testing, minification and much more, so developers can focus on solutions rather than worrying about the little things.
Yeoman is fast, performant and is optimized to work best in modern browsers.

想对比其他 Javascript 构建工具, Yeoman 具有下面非常吸引人的特点:

根据定制模板快速生成程序框架

Yeoman 能根据你选择的框架初始化生成程序框架, 目前已经支持大量的程序模板, 看趋势似乎是想把所有框架的初始化模板都包含进去:

Yeoman:
  generator
  controller

Angular:
  angular:service
  angular:all
  angular:directive
  angular:view
  angular:route
  angular:filter
  angular:controller
  angular:app

Testacular:
  testacular:app

Quickstart:
  quickstart:all

Bbb:
  bbb:all

Ember:
  ember:controller
  ember:all
  ember:view
  ember:model
  ember:app

Chromeapp:
  chromeapp:all

Ember-starter:
  ember-starter:all

Backbone:
  backbone:model
  backbone:view
  backbone:router
  backbone:collection
  backbone:app
  backbone:all

虽然目前我只用到了 Bbb 模板, 但还是得赞一下其模板的齐全.

Read on →

bbbinit 命令生成的初始化模板工程中包含有 backbone.layoutmanager 插件, 该插件提供了一种页面的结构化组织方式, 将 Backbone Views 组装成页面布局 Layout.

backbone.layoutmanager 主要的目的是提供一种规则来管理 Backbone.View 的渲染, 程序员只需要遵循这套规则, 就能简化页面渲染的实现. backbone.layoutmanager 主页已经很详细地介绍了使用方法, 这里就不再赘述. 下面是个人感觉在学习使用过程中感觉应当注意的几点:

完全受管理的 render

Backbone.LayoutView 仅仅是一个将 manage 属性设置成 trueBackbone.View.

backbone.layoutmanager V0.6.6
1
2
3
Backbone.LayoutView = Backbone.View.extend({
  manage: true
});

只有当 manage 属性被设置为 true, LayoutManager 才会接管 Backbone.View 的渲染.

数据和模板

视图的渲染需要 templateserialize 属性, 分别对应HTML模板和数据模型. LayoutManager 缺省使用 underscoretemplate 函数进行页面的渲染.

嵌套视图

可以通过 setView, setViews, insertView, insertViews 等函数在视图中嵌套多个其他的子视图.

BeforeRender 和 AfterRender

render 完全处在 LayoutManager 的管理下, 因此, 如果你想在每次视图渲染前后做一些特殊的处理, 必须定义 beforeRenderafterRender 函数. 由于 LayoutManager 内部会在渲染视图前移除所有附加模式的子视图, 因此, 通常在 beforeRender 函数中调用 setViewinsertView 来增加和设置子视图.

如果你不想在每次渲染时移除子视图, 自己控制子视图的增删, 可以设置子视图的 keep 属性为 true.

Cleanup 函数

很多视图(View)都有数据模型(model)的事件绑定函数, 因此, 必须在视图被删除后解除绑定. 可以通过定义视图的 cleanup 函数来完成这个解绑操作:

cleanup函数
1
2
3
4
5
6
7
8
9
10
11
12
var MyView = Backbone.View.extend({
  // The constructor binds the model's "change" event to the view's render function. 
  initialize: function() {
    this.model.on("change", this.render, this);
  }

  // This is a custom cleanup method that will remove the model events owned by
  // this View.
  cleanup: function() {
    this.model.off(null, null, this);
  }
});

自定义获取模版

LayoutManager 缺省只支持 script 标签的模版, 但是在实际软件项目中, 通常会将不同的模版放置在不同的单独的 html 文件中, 这样便于模版文件的管理. LayoutManager 提供了 fetch 配置项让我们有机会来自己获得模版文件:

从script标签中获得模版内容
1
2
3
4
  Backbone.LayoutManager.configure
    # Default fetch implementation, get template from `script` tag
    fetch: (path)->
      _.template $(path).html()
同步方式获取模版文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  JST = window.JST = window.JST or {}
  Backbone.LayoutManager.configure
    manage: true
    paths:
      layout: "templates/layouts/"
      template: "templates/"

    fetch: (path) ->
      path = path + ".html"
      unless JST[path]
        $.ajax(
          url: app.root + path
          async: false
        ).then (contents) ->
          JST[path] = _.template(contents)
      JST[path]

下面是作者的教学视频, 初学者一定要看看.

backbone.layoutmanager from tbranyen on Vimeo.