android 单元测试
很早一段时间之前我在做web项目的时候就接触过单元测试,因为那是后项目用到spring而spring中很重要的一点就是测试驱动开发。。。。这一点真的很重要,在web项目几乎是每一个类或者功能模块都有对应的测试用例!这样就提高了程序的质量从而在实际运行当中减少了程序出现bug的几率!
现在也做了这么长时间的android开发了。单元测试也接触了一些,但是之前的话旨在工作中使用并没有好好地回忆或者记录以及收录一下,以便于自己以后能更好的运用。那么今天就好好地
回忆一下吧。。(主要是因为现在项目也不是很紧,有点打酱油了。。)
好了入正题:
android单元测试的编写其实不难但是,方式有很多而且针对不同的android模块(我通常吧activity叫做viewservice以及后台的处理则成为service或者dao)也有不用的测试基类,其实仔细想想觉得测试真麻烦。。。擦擦的!
那么我们就按照模块来做测试吧。。
先看看dao层。。比如我们通常要处理的什么网络连接了。。。从服务端通过http下载的数据了。。(反正返回的是流。。我们只测试流就可以了),以及数据库的存储了。。还有什么文件的保存了。之类只要和service或者activity无关的我们都可以通过继承这样一个基类
那就是AndroidTestCase来进行单元测试。。。
下面我给出一些自己的通过sax解析xml的demo:(正好大家也可以学习一下sax解析了。。哈哈)
xml文件如下:
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23" class="a"> <name>张三</name> <age>123</age> <sex>0</sex> </person> <person id="22"> <name>小红</name> <age>25</age> <sex>1</sex> </person> </persons>
然后是实体类:
package com.test.domain; public class Person { private Integer id; private String name; private int age; private int sex; private String className; public String getClassName() { return className; } public void setClassName(String className) { this.className = className; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public Person(){} public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return this.id+",name:"+this.name+",age:"+this.age+",sex:"+this.sex+",className:"+this.className+"\n"; } }
接下来是我们的handler
package com.test.dao; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.test.domain.Person; import android.util.Log; public class SaxParserHandler extends DefaultHandler { private String tempString; private static final String NAMESTRING = "name"; private static final String AGESTRING = "age"; private static final String PERSONSTRING = "person"; private static final String IDSTRING = "id"; private static final String TAG = "SaxParserHandler"; private static final String SEXSTRING = "sex"; private static final String CLASSSTRING = "class"; private Person person; private List<Person> persons; private int temp = 0; @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); } @Override public void endDocument() throws SAXException { } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //先判断读到的元素是否是person if (PERSONSTRING.equals(localName)) { // 如果读到的是person这个元素 就要保存起来,保存在我们创建的那个person的类中 所以我们要new一个person类 person = new Person(); // attributes是属性。 Log.i(TAG, "attributes======"+attributes.getValue(temp)); temp++; person.setId(new Integer(attributes.getValue(IDSTRING))); if(attributes.getValue(CLASSSTRING)!= null){ person.setClassName(attributes.getValue(CLASSSTRING)); } } Log.d(TAG, "localName======"+localName); tempString = localName; Log.d(TAG, "tempString======"+tempString); } /** * 在遇到结束标签时调用此方法 */ public void endElement(String uri, String localName, String qName) throws SAXException { if(PERSONSTRING.equals(localName)&&person!=null) { persons.add(person); person = null; } tempString = null; } /** * 当读取xml中文本内容的时候才会调用 */ public void characters(char ch[], int start, int length) throws SAXException { if (person != null) { Log.w(TAG, "ch[]+++++++"+ ch); String valueString = new String(ch, start, length); if (NAMESTRING.equals(tempString)) { // 如果当前解析到的节点是name 就要将name中的文本节点元素的值得到 person.setName(valueString); } else if (AGESTRING.equals(tempString)) { person.setAge(new Integer(valueString).intValue()); } else if (SEXSTRING.equals(tempString)){ person.setSex(new Integer(valueString).intValue()); } } } public List<Person> getPersons(){ return persons; } }
备注:这个地方sax解析的时候写的不是很规范。。。先将就着这么用吧。。反正就是i一个demo
然后我们来看service
package com.test.service; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.SAXException; import com.test.dao.SaxParserHandler; import com.test.domain.Person; public class SaxReaderXml { public static List<Person> readXml(InputStream inputStream) throws ParserConfigurationException, SAXException, IOException{ SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = (SAXParser)factory.newSAXParser(); SaxParserHandler handler = new SaxParserHandler(); saxParser.parse(inputStream, handler); return handler.getPersons(); } }
最后我们来看测试类:
package com.test.junittest; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import org.xml.sax.SAXException; import android.test.AndroidTestCase; import android.util.Log; import com.test.domain.ApiIcfBean; import com.test.domain.Person; import com.test.service.SaxReaderIcfXml; import com.test.service.SaxReaderXml; public class ParserJunitTest extends AndroidTestCase { private static final String TAG = "ParserJunitTest"; public void testReadXml() throws Exception {//类装载器 InputStream inputStream = ParserJunitTest.class.getClassLoader().getResourceAsStream("component.xml"); List<Person> personsList = SaxReaderXml.readXml(inputStream); for (Iterator iterator = personsList.iterator(); iterator.hasNext();) { Person person = (Person) iterator.next(); Log.i(TAG, person.toString()); } } }
。。好了。。这样我们的整个单元测试的代码是完成了。。但是还需要一些配置那就是在
清单文件中配置、。。。具体配置如下:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.test"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="android.test.runner"/> </application> </manifest>
。。好了到这里位置。。我们已经可以做单元测试了。。。。
但是这里你看到的只仅仅是做dao层得单元测试。。
/******************************接下来我们说说activity和service的单元测试*******************************************/
那么接下来我们说说activity和service的单元测试
当我们在给你ui层做单元测试的时候我们得实现ActivityInstrumentationTestCase2<T>
里面的T就是你要测试的那个activity类的名字。。。
在这里我们要从写这个ActivityInstrumentationTestCase2基类的setup方法。。。
在这个里面我们需要把测试所用到的组件(比如buttonview之类的东西)在具体的测试方法之前给实例化了。。
然后才是我们相对应的testMethod。。。
同理service的测试则是实现ServiceTestCase<TextendsService>。。。。他和activity的测试相同。。这里不给出详细的解释了。。。。
其实除了这个创建测试的方式之外我们月还有另外一种方式。。但是这种方式的话是我们从新创建一个测试工程。在你创建androidproject的时候你可以看到。。。有一个androidtestproject项目的工程。。。。
就是它了。。在创建的过程中你只需要吧要测试的项目给build进入这个测试工程就行了
欢迎各位看客给出意见和建议。。以便于大家共同进步!谢谢!