1,安卓应用测试
1.1,黑盒测试,在不知道软件的源代码情况下测试(门槛低一些,不需要积累太多代码量,在我个人看来,更像是找一个高情商的人来测试程序,测试临界条件,非法参数等)
1.2,白盒测试,在知道应用程序的源代码情况下测试(黑盒测试的升级版,需要懂代码,又要懂得程序的各种边界,如:购物APP中是否为购买为负数的东西,日程安排app中能否给过去的日期安排行程之类)
1.3 值得注意的是,同样的工作经验下,白盒工资要比黑盒工资更高
2,测试的力度
2.1 单元测试 junit test
2.2 集成测试 intergration test
2.3 系统测试system test
3,测试的程度
3.1 压力测试(pressure test)(如:测试服务器单位时间内能承受多少次访问)
3.2 冒烟测试(smoke test)
4,ADT自带的测试 monkey(通过adb指令)adb shell>>>monkey 次数
5,安卓下的单元测试(类似javaweb中的单元测试,但是有些配置指令要注意)
5.1需要把应用程序部署到真实的手机或者模拟器,在dalvik虚拟机里面运行.
5.2执行步骤:
5.2.1,编写一个业务方法
5.2.2,编辑一个测试类,一般以test+需要测试的类命名,需要继承extends AndroidTestCase,测试类中的方法要以public开头,并且必须抛出异常
5.2.3,在清单中配置参数
<!-- 测试的指令集 -->
配置在<manifest>标签下
<instrumentation android:name="android.test.InstrumentationTestRunner
这里的包名是应用程序的包名
android:targetPackage="com.itheima.junit"></instrumentation>
<!-- 测试需要的jar包 -->
配置在<application>标签下
<uses-library android:name="android.test.runner"/>
6.Logcat视图
6.1在android项目中,不能直接通过Console输出内容,因为这些项目是部署在手机上的,所以出现的结果是在手机上的控制台上输出,对应的是Logcat视图中信息
6.2 因为Logcat中信息比较多,所以可以在左侧Saved Filters中添加筛选信息
6.3 android中定义了一个Log类,专门用来输出日志信息,
使用场景:程序使用的流程,网络获取的信息,业务逻辑比较复杂的时候(多线程的时候就不方便使用deBug调试)
使用的时候一般都封装一个Log工具类,用一个boolean类型的变量控制,是否打印,测试的时候设置为true打印,上线的时候(提交给客户)用false就不会打印
Log.v(tag,msg); //verbose提醒
Log.d(tag,msg); //debug调试
Log.i(tag,msg); //info信息
Log.w(tag,msg); //warn 警告
Log.e(tag,msg); //error 错误
Log.wtf(tag,msg); //什么鬼,重量级错误
在Logcat中预定了筛选信息,可以直接筛选,很方便
一般都把tag定义成成员变量,里面的值为MainActivity.class.getSimpleName()(对应类的名字,方便筛选错误)
7.数据储存
7.1.文件的读写创建需要在android指定的目录
/data/data/全包名(com.zzx.xxx)/文件名,其它就是 Java的文件存储IO流
直接创建文件,会创建在储存空间的根目录下,并且是无法读取的
7.2.写法简化版
File file = new File(目录,文件名);
(getFilesDir(),”infor.txt”);
这个方法是用来返回一个绝对路径(文件系统的绝对路径,省略了this(这里的this指的是context上下文))通过上下文获取路径.
getFilesDir() ===/data/data/全包名/文件名,
7.3.上下文:应用程序运行的环境
this.getFilesDir() ===/data/data/全包名/files/文件名
this.getCaCheDir()===/data/data/全包名/cache/文件名
这两个文件夹的区别:
Cache文件夹是缓存目录,清除时不会有提示,同时储存空间满了以后,会被系统自动清空掉.
Files 文件夹是保存重要的配置信息,清除时会有提示
7.4把数据储存在外存储(sd)卡中
需要配置清单权限: WRITE_EXTERNAL_STORAGE
READ_EXTERNAL_STORAGE
sd卡路径:/mnt/sdcard/info.text //但是这个路径根据不同的文件系统(手机)路径不一样
解决方法:使用api获取:Enviroment.getExternalStorageDirectory()
需要保证代码的健壮性:尽量让程序能够独立运行,降低外部的干扰:如路径不一致,返回为空这些情况,程序都能很好的处理.
检测sd卡是否存在:
String getExternalStorageState() 返回当前sd卡的状态
同时在Enviroment中还有一些常量:MEDIA_MOUNTED,已经安装好的sd卡
检测sd卡的可用空间
File getExternalStorageDirectory() 返回当前sd卡的目录对象
File getFreeSpace()(剩余空间)
File getUsableSpace()(可用空间)都返回一个long类型的数值,代表该目录对象的大小
//最小支持的的api是9
String Formatter.formatFileSize(this,size);返回一个String 类型的数据,代表容量大小
8 , 文件访问的权限
8.1 默认生成一个文件都是私有的,别的应用程序时无法读写的.
真实手机一般都没有root权限,所以可能是无法打开data/data/目录.
8.2 生成一个公开权限的文件
OpenFileOutput(name,mode);
Name:创建的文件名字
Mode:模式,是否全局可读,可写,默认不可读写,返回值是int类型,可以可读可写同时叠加
但是这两个常量都已经被废弃,这样创建的文件是有风险的,需要再次检查一遍(就是确认是否创建共有的文件,后面会讲到内容提供者,就能更好的去创建一个公开文件)
9,在DDMS下,查看文件资源系统,有一个项目叫Permission,可以看到对应的权限
d开头的是文件夹,-开头的是文件
rw - --- ---私有
rw- rw- rw- 公开
rw- rw- r-- 只读
rw- rw- -w- 只可写
文件的权限分为三种:创建这个文件的app:文件的所有者
文件所在的组:依赖的jar包,或者是其它应用程序,如:其它程序需要QQ授权的话,就需要让QQ能读这个文件,QQ中也有组文件,给别的文件访问.
其它用户:另外的一个app
linux中表现这个权限是用二进制表现的
如:rw- --- --- 110 000 000>>6 0 0
rw- rw- -w- 110 110 010>> 6 6 2
指令:chmod:change mode 更改文件的访问模式
通过cmd控制台 adb shell进入模拟器终端
移动到app私有文件夹Cd data/data/com.xxx.xxx/
ls -1 显示所有文件
Chmod 666 对应的文件名 修改权限
777为最高权限,可读可写,可执行
10,采用SharedPreferences保存数据(推荐)(谷歌提供的,别在java中用)
步骤:10.1,声明一个SharedPreferences ,
通过this(Context).getSharedPreferences(name,mode)获取到一个参数(类似文件对象).
Name:文件名称
Mode:一般写0,文件私有 0 =Activity.MODEXXXXXX
10.2,得到sp文件的编辑器
editor editor =sp.edit();
添加内容
editor.putString(文本名, 文本值),
editor.putString(也有其它put类型)(文本名, 文本值),
10.3,调用commit方法提交数据
editor.commit()提交数据
获取数据:怎么put数据,就怎么get出来的,也要先获得SharedPreferences对象
getString(文本名,文本不存在的时候的值)
这玩意不需要关流
11,采用SharedPreferences对象保存参数
练习:模拟系统控制中心
分割线:高度为1的View标签(View有开始也有结束,把属性写在开始标签里)
CheckBox方法:点击状态监听,isChecker布尔类型,是否被点击
setOnCheckedChangeListener()
SeekBar控件方法:拖动监听(开始拖动,结束拖动,正在拖动中)
setOnSeekBarChangeListener()
getProgress()获取拖动状态值,int数
12,xml序列化(serializer.attribute(命名空间.属性名.属性值)可以设置属性)
CheckedRadio方法 :getCheckedRadioButtonId()获得被选中的id
1,获取xml序列化器对象
Xml.newSerializer();
2,指定序列化器的初始参数
FileOutputStream os = new os(getFilesDir(),name+”.xml”);
serializer.setOutput(os,编码)
//3,开始写文件,生成开始结束标签,生成文本内容
serializer.startDocument(“utf-8”,是否独立(有无外部约束文件));
serializer.startTag(null,”属性名”);
Serializer.text(属性值);
serializer.endTag(null,”属性名”);
serializer.endDocument();
13,pull解析xml文件(javaweb有说过)(不过adt中已经集成了pull解析,所以不需要第三方jar包了)
其它解析:SAX解析,DOM解析,DOM4J解析
步骤:
①,获取到一个解析器
XmllPullParser xpp = Xml.newpullparser();
②,设置初始化参数
xpp.setInput(inputStream,encoding);
③解析文件
根据节点解析文件
XmllPullParser.START_TAG 开始节点
XmllPullParser.END_TAG 结束节点
Xpp.next()解析到下一个节点
xpp.getName()获取当前节点的名称
xpp.nextText()获取两个节点中的文本
14,其它,错误调试,debug,略
附 帮助文档中的pull解析示例
import java.io.IOException; import java.io.StringReader; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; public class SimpleXmlPullApp { public static void main (String args[]) throws XmlPullParserException, IOException { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) ); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if(eventType == XmlPullParser.START_DOCUMENT) { System.out.println("Start document"); } else if(eventType == XmlPullParser.START_TAG) { System.out.println("Start tag "+xpp.getName()); } else if(eventType == XmlPullParser.END_TAG) { System.out.println("End tag "+xpp.getName()); } else if(eventType == XmlPullParser.TEXT) { System.out.println("Text "+xpp.getText()); } eventType = xpp.next(); } System.out.println("End document"); } }