Snake's Home

snake


  • 首頁

  • 歸檔

  • 標籤
Snake's Home

acralyzer监控你的App

發表於 2016-01-07 | 分類於 android_test

本文发布在 搭建自己的 crash 监控系统

开发一个手机应用有如此多的限制,比如硬件限制(CPU,内存,电池等等)。如果你的代码不是足够合理,那就准备迎接世界上最严重的问题吧:Crash。根据研究所示:

应用崩溃是手机app用户抱怨最多的额问题

更严重的:

如果一个应用连续崩溃3次,大概一半的用户会卸载这个应用

崩溃追踪系统,让开发者能够从用户的设备上收集到每一个导致崩溃的细节,专门用来解决这种应用崩溃问题。目前最流行的2个流行崩溃追踪系统是 Crashlytics 和 Parse Crash Reporting,这两个服务都是免费的,开发者可以免费集成他们到你的app。当应用奔溃,整个跟踪报告就会发送到他们的后端,开发者可以及时快捷的修复这些严重的问题,这样,你就可以在很短的时间内奉上一个“无Crash”的应用。

然而,这些服务的提供商会收集这些数据,对于对用户隐私敏感的公司还是有些顾虑的。

那么。。。是否有那种允许我们在自己服务器部署的崩溃追踪系统?当然有!!并且会非常容易创建,下面有请Application Crash Reporting on Android (ACRA) 一个允许Android应用自动发送崩溃报告到自己服务器的库。

[翻译]如何安装ACRA

How to setup ACRA

git地址

以上都是在ubuntu上安装的步骤,我在Mac上实现了安装。

1. 安装couchdb数据库

1
Brew install couchdb

安装完成后,用如下指令来检验是否成功

1
2
3
4
5
6
➜  ~  couchdb
Apache CouchDB 1.6.1 (LogLevel=info) is starting.
Apache CouchDB has started. Time to relax.
[info] [<0.32.0>] Apache CouchDB has started on http://127.0.0.1:5984/
[info] [<0.108.0>] 127.0.0.1 - - GET / 200
[info] [<0.102.0>] 127.0.0.1 - - GET /favicon.ico 200

在浏览器中敲上 http://127.0.0.1:5984
你得到如此信息:

1
{"couchdb":"Welcome","uuid":"eba00733b63aab8847a954c2df76f432","version":"1.6.1","vendor":{"name":"Homebrew","version":"1.6.1_4"}}

恭喜你,数据库安装成功了。

2. 配置couchdb数据库

1
2
3
4
➜  ~  which couchdb
/usr/local/bin/couchdb
➜  ~  cd /usr/local/bin
➜  ~  subl couch-config

读读这个文件,大致知道文件都在啥位置

1
2
3
4
5
6
7
8
9
10
	staticdir="/usr/local/Cellar/couchdb/1.6.1_4/share/couchdb"
erlanglibdir="/usr/local/Cellar/couchdb/1.6.1_4/lib/couchdb/erlang/lib"
couchversion="1.6.1"
dbdir="/usr/local/var/lib/couchdb"
viewdir="/usr/local/var/lib/couchdb"
confdir="/usr/local/etc/couchdb"
urifile="/usr/local/var/run/couchdb/couch.uri"
logdir="/usr/local/var/log/couchdb"
erlangversion="18"
erlangbin="/usr/local/opt/erlang/bin/erl"

得到有用的信息:

1
confdir="/usr/local/etc/couchdb"

编辑/usr/local/etc/couchdb/local.ini 文件来允许我们通过外部IP来访问CouchDB(默认只能通关127.0.0.1来访问)。只需要把下面两行的注释去掉即可。

1
2
3
subl local.ini
;port = 5984
;bind_address = 127.0.0.1

然后修改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
port = 5984
bind_address = 0.0.0.0
```


在这个文件里,你还应该添加一个用户名/密码来作为管理员账户,找到这一行(一般是在文件末尾):

[admins]

在它的下一行添加一个 username=password形式的内容。例如:


``` bash
admin= 12345

; changing this.
[admins]
admin = 123456

不用担心在这里写明文密码会不会有问题,一旦CouchDB重启后,你的密码会被自动哈希加密,并且是不可读的
保存文件,通过下面的语句来重启CouchDB:

1
2
3
4
~  couchdb
Apache CouchDB 1.6.1 (LogLevel=info) is starting.
Apache CouchDB has started. Time to relax.
[info] [<0.32.0>] Apache CouchDB has started on http://0.0.0.0:5984/

现在,你就可以通过浏览器来访问CouchDB了,网页服务被称为Futon—CouchDB的界面后端。通过以下地址来打开浏览器:
http://localhost:5984/_utils/

多了两数据库。

CouchDB

3. 配置couchdb本地数据库

首先,你需要通过之前设定的管理员账户来登录系统

否则,后面的操作会出现如下错误:

1
2
[error] [<0.408.0>] httpd 500 error response:
 {"error":"unauthorized","reason":"unauthorized to access or create database acra-myapp"}

现在我们要安装一个acro-storage(Acralyzer的存储端)。通过右侧的菜单,点击Replicator(复制器),并填写表单的from Remote Database和from Remote Database类似如下所示:

from Remote Database: http://get.acralyzer.com/distrib-acra-storage

to Local Database: acra-myapp

然后点击Replicate,等待它完成。

成功后出现如下界面

acro-storage

然后使用类似的方法安装Acralyzer:

from Remote Database: http://get.acralyzer.com/distrib-acralyzer

to Local Database: acralyzer

如果你上面做的都对的话,你会发现系统里多了2个数据库—-acra-myapp 和 acralyzer.

dbs

离成功很近了,下一步,我们要创建用户,打开浏览器,转到这个网址:

http://localhost:5984/acralyzer/_design/acralyzer/index.html

进入 Admin 页并点击 Users,

users

空间不能放太多照片,请移步以下链接。

本文发表在 Testerhome

Snake's Home

ImageMagick

發表於 2016-01-05 | 分類於 工具

最近看了一下ImageMagick, 感觉很强大的。
因为有IOS app用了这个来区分环境,版本。打算好好研究一下。
我是在 Mac 上用 brew 安装的:

1
brew install imagemagick

但是执行起来老报错:

1
Error while running convert: convert: unable to read font

网上搜了 一下,有解决方案:

1
$ brew install ghostscript

参照:ImageMagick: Error convert: unable to read font

然后自己本地尝试了一下,也成功了。

1
convert -background '#0008' -fill white -gravity center  caption:"debug"  mediahub_icon.png +swap -gravity south -composite mediahub_icon3.png

ImageMagick 主要的命令还是 convert
初始图像
尝试了几个命令:

1
convert -fill black -pointsize 10 -font helvetica -draw 'text 10,10 "Hello, World!"'  snake.jpg  helloworld.jpg

效果
在图像的10,10 位置采用10磅的全黑Helvetica字体写上 Hello, World!

1
convert snake.png -fill red -pointsize 13 -draw "text 10,15 'snake'" 1112.png

效果

1
convert -background '#0008' -fill white -gravity center  caption:"debug"  snake.png +swap -gravity south -composite snake111.png

效果
更多的命令:
ImageMagick之convert命令大全
回头继续研究一下。
未完待续。。。

Snake's Home

测试估时

發表於 2015-12-28 | 分類於 职业

原文链接:
http://www.softwaretestinghelp.com/software-test-estimation-how-to-estimate-testing-time-accurately/

产品的成功与否,离不开测试。而测试中估时是非常重要。
现在大部分公司都实行敏捷模式,开发需要估时,测试也需要估时,不然会影响整个项目周期。
估时的原则是: 实际,精确。
这里不讨论测试估时的具体实施,只是讨论一下如何让测试估时更加实际,更加精确。

1)给自己留有余地

估时的时候需要给自己留一点风险时间,留有余地。任何事情都不是理想状态的,留有余地的话确保在不利的情况下也有时间对付。

2)充分考虑公司的流程

有的公司流程制定,留给测试的时间非常少。那么,需要做哪些测试,哪些有更高的优先级。出现问题怎么解决,这些都是在测试前就预估好的。
比如有些公司一个发布过程,要走开发环境,测试环境,生产环境。但是服务器都不稳定,有可能就会block。

3)并行测试

有些story没有太大的依赖,是不是可以一起测了。或者在开发刚开始的时候,是不是可以把一些准备工作给做了,比如创建帐号,准备testcase,准备一些自动化脚本等。

4)随时关注进度,重估时间

因为有很多不可预见的因素,项目没有预期进行。或者开始估计就有偏差,那么随时要校正预估时间。

5)考虑下过去的经验

过去的经验,能让你预计可能的风险,和应对策略,让估时更加精确,实际。

6)目标明确

很多时候,并不是需要把所有的bug都要解决了,一个release的范围是什么?产品需求的细节是啥?心里都要很清楚。不然就会偏差很大,引起delay, 或者加班。

7)了解你的团队

如果你是team leader, 你需要很明白你团队的战斗力,谁的专长是啥,谁做哪块会更好。

8)了解你的资源

估时的时候,都是要以现有的资源为依托,不要相信领导说的,在某个时段招个人。很多时候,招人并不能起到显著的效果。而且招人也没有那么迅速成长;或者领导,HR只是说说而已。

9) 取决于你,你的公司,你的领导

根据公司,领导对测试的重视程度不一样,给测试的时间也会不一样。有的时候,要从产品质量的方面考虑,争取一些时间。有的时候,测试估的时间多了,项管肯定不干。
如果不争取,估计会被压得很厉害,天天加班,团队不稳定。或者产品的质量更本没法保证。
有的时候,别的部门会认为测试很简单,分分钟就能搞定,不就是点点鼠标吗?质量深入人心很重要。

Snake's Home

mongodb+rails

發表於 2015-12-28 | 分類於 DB

要维护一个项目,但是这个项目是rails+mongodb的,之前用惯了mysql,突然换成mongodb,不是很习惯,而且关于这块的资料好少。
自己折腾了下,总结过程如下:

安装

1
Brew install mongodb

然后

1
which mongo

来找到mongo的安装路径
添加环境变量:

1
2
3
vi .bahs_profile
Export /usr/ocal/cellar/mongodb/3.0.7/bin:$PATH;
Source .bash_profile

然后启动mongo 服务:

1
mongod --config /usr/local/etc/mongod.conf

敲上mongo就可以操作数据库了

与rails结合

在Gemfile中添加:

1
2
source 'https://ruby.taobao.org'
gem "mongoid", "~> 4.0.0"

然后

1
bundle install

再执行:

1
rails g mongoid:config

将会出现:

1
This generates config/mongoid.yml

那么,之前那个默认的database.yml配置文件已经没用了,别舍不得,去./config目录里面随手删掉它吧!

修改config/application.rb文件,先删掉

1
require "rails/all"

和

1
config.active_record.raise_in_transactional_callbacks = true

这两行,再添加以下几行:

1
2
3
4
5
require "action_controller/railtie"
require "action_mailer/railtie"
# require "active_resource/railtie" # Comment this line for Rails 4.0+
require "rails/test_unit/railtie"
require "sprockets/railtie" # Uncomment this line for Rails 3.1+

修改config/environments/development.rb文件,将里面所有涉及到active_record的配置项都注释掉:

1
config.active_record.migration_error = :page_load

在config/initializers/目录下新建一个mongoid.rb文件,添加一行:

1
Mongoid.load!("config/mongoid.yml", :production)

使用

经过上面的配置,就可以开始使用了,现在请忘记rake db:migrate命令吧,需要添加修改字段只要修改对应的model文件即可。

1
2
3
4
5
class Person
include Mongoid::Document
field :first_name, type: String
field :last_name, type: String
end

就ok了

相关Gems

• 如果觉得mongode生成的objectid在url中显示不够美观的话,那么可以安装mongoid_auto_increment_id来生成自增的整数形id。

• 使用mongoid-rails可以防止query的注入

• 因为在替换成mongoid之后,默认的migratetion就已经不能用来了,所以可以用mongoid_rails_migrations来实现针对mongodb的数据迁移功能。

参考:
TY’s Blog
xiaozhou’s Blog

Snake's Home

台湾之行

發表於 2015-10-31 | 分類於 生活

感谢我厂,把这次年会放到了台北。才使我这样的土鳖,有机会出去瞅瞅。

首先是痛苦的办证过程。最后还是得感谢房东,提供了房产证明。才在最后的时刻办上了临时居住证,后面的顺利多了。

台湾之行是愉快的。 无论是公司里面的老外,还是见多识广的海龟,还是比较小资上海拧,还是我这种没出去过的土鳖。每个人都觉得很愉快。

台北没有上海这样多的高楼大厦。看起来甚至不如一个内陆的二线城市。跟大陆任何一个城市没多大的区别,除了繁体字。可能是软实力吧,藏富于民。

无论走到哪个大街小巷,本地人的精神状态很好,很礼貌热情。可能没有房贷,医疗,教育各个方面的压力吧。

台北的物价没有上海的高,遍布各个大街小巷的都有物美价廉,新鲜绿色的水果,夜市小吃。

去了下西门汀,日据时代日本人的聚集地。现在还有很多日本人在那居住。
台湾的日本人很多,台湾人根本不排斥日本人。台湾处处有日本的痕迹。
就像在台北故宫参观。大陆游客都是走马观花,日本人韩国人却能很规矩的一个一个欣赏,认真听讲解。

台湾跟大陆同宗同源,去台湾,就跟去香港差不多。没有语言 ,文化上的差异。很多传统,在台湾都有保留。比如儒家的那套“仁,义,礼,智,信,忠,孝,廉,耻”在台湾就有很好的保留和发扬,从道路命名就可以看出来。

整个行程很短暂,留下的都是些美好记忆。

有机会,世界各地多走走。
行千里路,读万卷书。。。

Snake's Home

Python中的config配置

發表於 2015-07-22 | 分類於 python

Python中有ConfigParser类,可以很方便的从配置文件中读取数据(如DB的配置,路径的配置),所以可以自己写一个函数,实现读取config配置。

config文件的写法比较简单,[section]下配置key=value,一下是例子:db.conf

1
2
3
4
5
6
7
8
#配置数据库  
[database]
dbhost=127.0.0.1
dbport=3366
dbname=test
dbuser=test
dbpassword=test
dbcharset=utf8

接着写一个读取config的方法模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#encoding:utf-8  
#name:mod_config.py

import ConfigParser
import os

#获取config配置文件
def getConfig(section, key):
config = ConfigParser.ConfigParser()
path = os.path.split(os.path.realpath(__file__))[0] + '/db.conf'
config.read(path)
return config.get(section, key)

#其中 os.path.split(os.path.realpath(__file__))[0] 得到的是当前文件模块的目录

ConfigParser 是Python自带的模块, 用来读写配置文件, 用法及其简单。 直接上代码,不解释,不多说。

配置文件的格式是: []包含的叫section, section 下有option=value这样的键值
配置文件:test.conf

1
2
3
4
5
6
7
[section1]  
name = anderson
sex = male

[section2]
ip = 192.168.1.1
port = 8080

读写

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
# -* - coding: UTF-8 -* -    
import ConfigParser

conf = ConfigParser.ConfigParser()
conf.read("c:\\test.conf")

# 获取指定的section, 指定的option的值
name = conf.get("section1", "name")
print(name)
age = conf.get("section1", "age")
print age

#获取所有的section
sections = conf.sections()
print sections

#写配置文件

# 更新指定section, option的值
conf.set("section2", "port", "8081")

# 写入指定section, 增加新option的值
conf.set("section2", "IEPort", "80")

# 添加新的 section
conf.add_section("new_section")
conf.set("new_section", "new_option", "http://xieming.github.io")

# 写回配置文件
conf.write(open("c:\\test.conf","w"))

数据库配置

1
2
3
4
5
[dbsetting]
host = 10.128.0.1
user = BOSTON\anderson
password = Good
database = ET_Main

数据库操作:

连接的是sqlserver,要安装pymssql这个模块。
mac上操作:

1
pip install pymssql

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
33
34
__author__ = 'anderson'

#!/usr/bin/env python
#coding=utf-8
import sys
import pymssql
import ConfigParser


cf = ConfigParser.ConfigParser()
#read config
cf.read("ini.conf")
hostcf = cf.get("dbsetting", "host")
usercf = cf.get("dbsetting", "user")
passwordcf = cf.get("dbsetting", "password")
databasecf = cf.get("dbsetting", "database")

print(hostcf)



def execdb(query,querystr):
try:
conn = pymssql.connect(host=hostcf,user=usercf,password=passwordcf, database=databasecf)
except pymssql.OperationalError, msg:
print "error: Could not Connection SQL Server!please check your dblink configure!"
sys.exit()
else:
cur = conn.cursor()

#query="SELECT TOP 10 * FROM dbo.Members WHERE username = user"
print query
cur.execute(query)
conn.commit
Snake's Home

Nginx+Passenger+Rails

發表於 2015-06-15 | 分類於 Nginx

当网站做好了之后,需要部署,部署的方法有很多,这里就简单介绍在 Mac 下用 Nginx + Passenger 部署 Rails 的运行环境。

假设已经配置好了ruby,rails等环境。

1.安装Passenger + Nginx

1
2
3
4
5
6
$ gem install passenger
$ passenger-install-nginx-module

Whichever you choose, if you already have an existing Nginx configuration file,
then it will be preserved.
Enter your choice (1 or 2) or press Ctrl-C to abort:

这里建议选择1

1
Please specify a prefix directory [/opt/nginx]: /usr/local/nginx

当询问nginx的安装路径的时候,个人建议安装到/usr/local/nginx下

当安装完成后,会在console中提示如何配置Nginx
Passenger会自动帮你将下面两行添加到Nginx的配置文件中/usr/local/nginx/conf/nginx.conf(很人性化)

1
2
3
4
5
6
7
8
9
10
11
12
13
http {
...
passenger_root /Users/Daniel/.rvm/gems/ruby-1.9.2-p290/gems/passenger-3.0.10;
passenger_ruby /Users/Daniel/.rvm/wrappers/ruby-1.9.2-p290/ruby;
...
}

server {
listen 80;
server_name www.yourhost.com;
root /somewhere/public; # <--- be sure to point to 'public'!
passenger_enabled on;
}

2.配置Nginx + Passenger + Rails
修改hosts文件,给你的项目一个本地域名, 比如awesome_project.local

1
2
$ sudo vim /etc/hosts
127.0.0.1 awesome_project.local

测试hosts

1
2
$ ping awesome_project.local
PING awesome_project.local (127.0.0.1): 56 data bytes

继续配置Nginx, 这里我给出一个最小可运行的Nginx配置文件

1
$ vim /usr/local/nginx/conf/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
worker_processes  1;
events {
worker_connections 1024;
}
http {
passenger_root /Users/Daniel/.rvm/gems/ruby-1.9.2-p290/gems/passenger-3.0.10;
passenger_ruby /Users/Daniel/.rvm/wrappers/ruby-1.9.2-p290/ruby;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name awesome_project.local;
root /Users/Daniel/awesome_project/public;
passenger_enabled on;
rails_env development;
}
}

测试Nginx的配置文件语法是否正确

1
2
3
$ sudo nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

启动Nginx

1
$ sudo nginx

如何在修改Nginx的配置文件后,让Nginx载入新配置

1
$ sudo nginx -s reload

如何停止Nginx

1
$ sudo nginx -s stop

如何在不停Nginx的情况下,重新启动Passenger

1
2
$ cd path/to/your/awesome/project
$ touch tmp/restart.txt

好了,这个时候你可以打开浏览器,访问你的awesome_project网站了

1
http://awesome_project.local

有时候,需要到 /usr/local/nginx/sbin/
执行:

1
Sudo ./nginx

问题来了,启动后一直显示”welcome to nginx”
解决方案:在conf文件里注释掉

1
2
3
4
# location / {
# root html;
# index index.html index.htm;
# }

参考:

通过Nginx在一台服务器上部署两个Rails项目

如何在 Mac 下用 Nginx + Passenger 部署 Rails 的运行环境

Ruby专题

Snake's Home

rails实现文件上传

發表於 2015-06-05 | 分類於 rails

最近一直在折腾上传,对mongo的上传搞伤脑经。

rails 上传主要是一个gem carrierwave
先生成一个项目,然后对Gemfile做点修改,如下:

1
2
3
4
5
6
7
source 'https://ruby.taobao.org'

gem 'mongoid', '~> 4.0.0'
gem 'carrierwave-mongoid'
gem 'carrierwave', '0.6.2'
gem 'mini_magick' #不使用rmagick,占内存
gem 'fog' #用来在生产环境中上传图片

然后安装

1
2
bundle install
rails g mongoid:config

将会出现:

1
This generates config/mongoid.yml

那么,之前那个默认的database.yml配置文件已经没用了,别舍不得,去./config目录里面随手删掉它吧!

修改config/application.rb文件,先删掉

1
require "rails/all"

和

1
config.active_record.raise_in_transactional_callbacks = true

这两行,再添加以下几行:

1
2
3
4
5
require "action_controller/railtie"
require "action_mailer/railtie"
# require "active_resource/railtie" # Comment this line for Rails 4.0+
require "rails/test_unit/railtie"
require "sprockets/railtie" # Uncomment this line for Rails 3.1+

修改config/environments/development.rb文件,将里面所有涉及到active_record的配置项都注释掉:

1
config.active_record.migration_error = :page_load

在config/initializers/目录下新建一个mongoid.rb文件,添加一行:

1
Mongoid.load!("config/mongoid.yml", :production)

然后启动mongo服务:

1
mongod --config /usr/local/etc/mongod.conf

生成一个scaffold

1
2
3
rails generate scaffold User name:string nick:string avatar:string

rails generate uploader Avatar

未完待续。。。

Snake's Home

pyqrcode

發表於 2015-05-29 | 分類於 python

最近对二维码生成比较感兴趣,发现python本来就有qrcode这个插件。
先是Python使用QRCode模块生成二维码

但是他的安装方法已经失效。
我去官网看了一下qrcode|python

我的安装方法很简单:

1
2
sudo easy_install pillow
sudo easy_install qrcode

一下就安装成功了。

简单用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import qrcode 
img = qrcode.make('hello, qrcode')
img.save('test.png')
```

```python
import qrcode
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data('xieming.github.io')
qr.make(fit=True)
img = qr.make_image()
img.save('andersoon.png')

高级用法

1
2
3
4
5
6
7
8
9
10
11
import qrcode 
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data('hello, qrcode')
qr.make(fit=True)
img = qr.make_image()
img.save('123.png')

参数含义:
version:值为1~40的整数,控制二维码的大小(最小值是1,是个12×12的矩阵)。 如果想让程序自动确定,将值设置为 None 并使用 fit 参数即可。

error_correction:控制二维码的错误纠正功能。可取值下列4个常量。
  ERROR_CORRECT_L:大约7%或更少的错误能被纠正。
  ERROR_CORRECT_M(默认):大约15%或更少的错误能被纠正。
  ROR_CORRECT_H:大约30%或更少的错误能被纠正。

box_size:控制二维码中每个小格子包含的像素数。

border:控制边框(二维码与图片边界的距离)包含的格子数(默认为4,是相关标准规定的最小值)
尝试了一下带图标的,没有成功,先不管了。

1
sudo easy_install image

qrcode|图标

Snake's Home

robotium测试读取sd卡

發表於 2015-03-08 | 分類於 java

当时为了解决帐号问题,用robotium 测试时,先将帐号写到sd.然后实现读出来,解决帐号冲突。

page.java

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package com.XXXcircle.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;

import android.os.Environment;

public class Page {

final String FILE_NAME = "/number.txt";
// guidepage
public String guideActivity = "com.XXX.app.activity.GuideActivity";
public String guidepagebtn = "guide_page_btn";

// Login Page
public String LoginNewActivity = "com.XXX.app.activity.LoginNewActivity";
public String username = "login_account_et";
public String password = "login_password_et";
public String loginbtn = "login_btn";
public String HomeActivity = "HomeActivity";

// Logout Page
public String backbtn = "widget_custom_titlebar_right_gamma_btn";
public String popuptext = "popup_text";
public String settingmainactivity = "SettingMainActivity";
public String settingmianlayout = "setting_main_about_XXX_layout";
public String settingmainquit = "setting_main_quit";
public String positivebtn = "positiveButton";

// Home Page
public String homeactivity = "com.XXX.app.activity.HomeActivity";

// 动态
public String XXXtab = "page_home_XXX_tab_btn";
// 联系人
public String contactstab = "page_home_contacts_tab_btn";
// 探究
public String discovertab = "page_home_discover_tab_btn";

// 我
public String profiletab = "page_home_profile_tab_btn";
// 查找
// public String searchbtn = "widget_custom_titlebar_right_alpha_btn";
// 查找(放大镜)
public String searchbtn = "widget_custom_titlebar_right_beta_btn";
// 设置(加号)
public String setbtn = "widget_custom_titlebar_right_gamma_btn";

// 查找
public String SearchActivity = "com.XXX.app.activity.SearchActivity";
public String searchbtnet = "page_search_content_et";
public String searchcancelbtn = "page_search_cancel_btn";
public String searchbackbtn = "page_search_back_ib";

// 添加好友
public String searchfriendactivity = "SearchFriendActivity";
// 查找框
public String editsearch = "edit_searchfriends";
// 清空
public String searchdel = "txt_search_del";
// 搜索按钮
public String searchclick = "txt_search_click";
// 好友推荐
public String recommend = "iv_recommend_icon";
// 扫一扫
public String saoyisao = "iv_er_icon";
// 结果
public String finduserresultactivity = "com.XXX.app.activity.FindUserResultActivity";
public String backupbtn = "widget_custom_titlebar_back_btn";

// 公共群聊天
public String orgroup = "img_organizationgroup";
public String publictalkgroupactivity = "com.XXX.app.activity.PublicTalkGroupListActivity";
public String txtgroup = "txt_group";
public String talkgroupicon = "iv_talkgroup_icon";
public String chatactivity = "com.XXX.app.activity.ChatActivity";
public String chataudiobtn = "page_chat_message_et";
public String chatmessagesendbtn = "page_chat_message_send_btn";

// 探究
// 动态
public String customimgview = "widget_custom_imgview_iv";
public String discoveractivity = "com.XXX.app.activity.DiscoverActivity";
// 笔的标志
public String releasebtn = "release_dynamic_btn";

// 我
public String settingactivity = "com.XXX.app.activity.SettingMainActivity";
public String mysetting = "r_mysetting";

/*
* 通过ID输入文本内容 enterTextById( String id, String s,int t)
* id:Id(hierarchviewer)获取的文本框id,字符串格式id s:需要输入的文本信息 t:timedelay
* 触发按键后,停留多久(ms)
*/


/*
* public int enterTextById( String id, String s, int t) { int ctrl;
* EditText v;
*
* if (s == "") { return -1; } //
* ctrl=solo.getCurrentActivity().getResources
* ().getIdentifier(id,"id",solo.getCurrentActivity().getPackageName());
* View ctr = solo.getView(id); v = (EditText) (ctr);
*
* // 先清空 solo.clearEditText(v); solo.enterText(v, s); solo.sleep(t); return
* 0; }
*
*
*
* 通过ID点击打开VIEW clickCtrlById( String s,int t)
* s:Id(hierarchviewer)触摸按键的id,字符串格式 t:timedelay 触发按键后,停留多久(ms)
* TARGET_PACKAGE_ID,是一个宏变量,字符串格式,定义了目标APK的包名
*
* public int clickCtrlById( String s, int t) { int ctrl; View v; if (s ==
* "") { return -1; } ctrl = solo.getCurrentActivity().getResources()
* .getIdentifier(s, "id", "com.leju.platform"); v = solo.getView(ctrl);
* solo.clickOnView(v); solo.sleep(t); return 0; } /* /*
* /**我的需求是找列表中符合某种条件的Item可以点进去查看思路:滑动一个,判断一个,也就是说,每次点击的都是当前屏幕的第一个
*
* public void findItem() { solo.sleep(_1S); //获取listView 随便怎么获取 ListView
* listView = solo.getView(ListView.class, 0);
*
* if (listView.getCount() == 0) { assertEquals("", "列表为空"); } int clickLine
* = 1; int oneScreenCount = listView.getChildCount(); for (int index = 0,
* size = listView.getCount(); index < size; index++) { log("列表点击第" + (index
* + 1) + "个"); solo.clickInList(clickLine); if ( your conditions) {
* log("列表符合条件的是第" + (index + 1) + "个"); //break; return; } if (index >=
* (size - oneScreenCount) || (size <= oneScreenCount)) { //滑动到了列表的最后一屏
* clickLine = clickLine + 1; } else { clickLine = 1; } if (index == (size -
* 1)) { assertEquals("", "当前没有符合条件的东西"); } solo.goBack();
* solo.scrollListToLine(0, index + 1); }
*
* //如果return换成break 此时点击clickLine就是你想要的了 //solo.clickInList(clickLine); }
*
*
* RelativeLayout parentView =
* (RelativeLayout)solo.getView("pic_lick_num_id").getParent(); LinearLayout
* linearlayout=(LinearLayout)parentView.findViewById(1);
* linearlayout.getChildAt(0);
* solo.clickOnView(solo.getView("gallery_flower_btn"));
*
*
* try { View fastLoginDialog = solo.getView("xxxxxxx:id/has_account",0);
* solo.clickOnView(fastLoginDialog);
*
* View username = solo.getView("xxxxxxx:id/edit_account",0); EditText un =
* (EditText)username; solo.typeText(un, "hh1906"); View pwd =
* solo.getView("xxxxxxx:id/edit_pwd",0); EditText pw = (EditText)pwd;
* solo.typeText(pw, "123456"); solo.clickOnButton("登 录");
* Thread.sleep(5000);
*
*
* } catch (AssertionFailedError e) { //登录操作 View rb =
* solo.getView("xxxxxxx:id/right_bt",0); solo.clickOnView(rb); View avatar
* = solo.getView("xxxxxxx:id/avatar",0); solo.clickOnView(avatar); View
* username = solo.getView("xxxxxxx:id/edit_account",0); EditText un =
* (EditText)username; solo.typeText(un, "hh1906"); View pwd =
* solo.getView("xxxxxxx:id/edit_pwd",0); EditText pw = (EditText)pwd;
* solo.typeText(pw, "123456"); solo.clickOnButton("登 录");
* Thread.sleep(5000);
*
* }
*/

private void write(String content) {
try {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 获取SD卡的目录
File sdCardDir = Environment.getExternalStorageDirectory();
File targetFile = new File(sdCardDir.getCanonicalPath()
+ FILE_NAME);
// 以指定文件创建RandomAccessFile对象
RandomAccessFile raf = new RandomAccessFile(targetFile, "rw");
// 将文件记录指针移动到最后
raf.seek(targetFile.length());
// 输出文件内容
raf.write(content.getBytes());
raf.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}

public String read() {
try {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 获得SD卡对应的存储目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 获取指定文件对应的输入流
FileInputStream fis = new FileInputStream(
sdCardDir.getCanonicalPath() + FILE_NAME);
// 将指定输入流包装成BufferReader
BufferedReader br = new BufferedReader(new InputStreamReader(
fis));
StringBuilder sb = new StringBuilder("");
String line = null;
// 循环读取文件内容
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
return sb.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Object[] splitstring(String number) {

Object[] numberArray=number.split(",");
//Object[] o = new Object[2];
//o[1]=numberArray[1];
//o[2]=numberArray[2];
return numberArray;
}

}

ddfriends.java

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
33
34
35
36
37
38
39
package com.XXXcircle.testcases;


import org.testng.annotations.Test;

import com.XXXcircle.action.addfriendsaction;
import com.XXXcircle.action.chataction;
import com.XXXcircle.test.Page;



public class addfriends extends addfriendsaction{

/*
public void testread(){
Page page = new Page();
String a=page.read();
Object[] as= page.splitstring(a);
System.out.print(as[0]);
System.out.print(as[1]);
}
*/


public addfriends() throws ClassNotFoundException {
super();

}

public void testaddfriend() throws ClassNotFoundException{
Page page = new Page();
String a=page.read();
Object[] as= page.splitstring(a);
//System.out.print(as[0]);
//System.out.print(as[1]);
//testread();
testaddfriends(as[0].toString(), as[1].toString(),"尼玛坤爷");

}
}
1…4567
Snake

Snake

不要被困难击倒,除非你躺着睡大觉

69 文章
17 分類
57 標籤
© 2017 Snake
由 Hexo 強力驅動
主題 - NexT.Muse