单元测试、SQLite与ListView

测试

测试分类

  • 黑盒测试
    • 测试逻辑业务
  • 白盒测试

    • 测试逻辑方法
  • 根据测试粒度

    • 方法测试:function test
    • 单元测试:unit test
    • 集成测试:integration test
    • 系统测试:system test
  • 根据测试暴力程度

    • 冒烟测试:smoke test(例如monkey 1000:在屏幕上随机点击1000次)
    • 压力测试:pressure test

Android中的单元测试

首先要使用一个类继承自AndroidTestCast:

import android.test.AndroidTestCase;

public class Test extends AndroidTestCase {
    public void test(){
        //TODO 测试的代码或者方法
    }
}

并且在中做出如下配置:

<instrumentation android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="要测试的应用包名">
</instrumentation>
<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <!-- 只有这一个属性就是android.test.runner -->
        <uses-library android:name="android.test.runner"/>
</application>

SQLite

  • 轻量级关系型数据库

  • 创建数据库需要使用的api:SQLiteOpenHelper

    • 数据库被创建时会调用:onCreate方法
    • 数据库升级时会调用:onUpgrade方法
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    
    public class MyOpenHelper extends SQLiteOpenHelper {
    
    public MyOpenHelper(Context context) {
        //参数说明:上下文、数据库名称、游标工厂(默认使用NULL)、版本(用于升级)
        super(context, "test.db", null, 1);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        //创建表
        db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20), salary integer(10))");
    }
    
    //数据库升级的时候调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        System.out.println("数据库升级...");
    }
    }

创建数据库

//创建OpenHelper对象
MyOpenHelper oh = new MyOpenHelper(getContext(), "test.db", null, 1);
//获得数据库对象,如果数据库不存在,先创建数据库,后获得,如果存在,则直接获得
SQLiteDatabase db = oh.getWritableDatabase();
  • getWritableDatabase():打开可读写的数据库
  • getReadableDatabase():在磁盘空间不足时打开只读数据库,否则打开可读写数据库

数据库的增删改查

数据库的增删改查可以自己使用SQL语句,然后db.execSQL("SQL语句")即可完成!

注意:setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作。

@Override
protected void setUp() throws Exception {
    super.setUp();
    //获取虚拟上下文对象
    oh = new MyOpenHelper(getContext(), "test.db", null, 1);
}
@Override
protected void tearDown() throws Exception {
    super.tearDown();
    //关闭数据库
    db.close();
}

使用API实现增删改查

//使用游标来逐个访问每条数据
public void select(){
        Cursor cursor = db.rawQuery("select * from 表名", null);
        //把指针移动至下一行
        while(cursor.moveToNext()){
            //先通过列名,获取列索引,然后再获取该列的内容
            String str = cursor.getString(cursor.getColumnIndex("字段名1"));
            String str2 = cursor.getString(cursor.getColumnIndex("字段名2"));
            int str3 = cursor.getInt(cursor.getColumnIndex("字段名3"));
            System.out.println(str+str2+str3);
        }
}
public void insertApi(){
        ContentValues values = new ContentValues();
        values.put("字段1", "value");
        values.put("字段2", "value");
        values.put("字段3", "value");
        //返回值-1,插入失败
        long l = db.insert("表名", null, values);
}

public void deleteApi(){
        //因为后面要传入的是对象数组
        int i = db.delete("表名", "_id = ?", new String[]{"4"});
}

public void updateApi(){
        ContentValues values = new ContentValues();
        values.put("字段名", "value");
        int i = db.update("表名", values, "_id = ?", new String[]{"1"});
}

事务

保证多条SQL语句要么同时成功,要么同时失败,失败的话会发生回滚!

public void transaction(){
        try{
            //开启事务
            db.beginTransaction();

            //TODO 修改表数据...

            //设置事务执行成功,提交时如果这行代码没有执行过,就会回滚
            db.setTransactionSuccessful();
        }
        catch (Exception e) {
             //这里的异常必须要捕获
            e.printStackTrace();
        }
        finally{
            //关闭事务,提交数据
            db.endTransaction();
        }
}

ListView

  • 用于显示列表

  • MVC结构

    • M:model模型层,要显示的数据 ————people集合
    • V:view视图层,用户看到的界面 ————ListView
    • c:control控制层,操作数据如何显示 ————adapter对象
  • 每一个条目都是一个View对象

    BaseAdapter

  • 必须实现的两个方法

    // 适配器类
    class MyAdapter extends BaseAdapter {
        // 系统调用:获取模型层数据的数量
        @Override
        public int getCount() {
            return list.size();
        }
    
        // 系统调用:获取要显示至ListView的View对象
        // convertView:系统之前缓存的条目
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            People p = list.get(position);
            View view = null;
            if (convertView == null) {
                // 把布局文件填充为view对象(看源码,这就是三种方式)
                // LayoutInflater layIn = LayoutInflater.from(MainActivity.this);
                // LayoutInflater layIn = (LayoutInflater)getSystemService("layout_inflater");
                // view = layIn.inflate(R.layout.item_listview,null);
                view = View.inflate(getApplicationContext(),R.layout.item_listview, null);
    
            } else {
                view = convertView;
                TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
                TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
                TextView tv_sa = (TextView) view.findViewById(R.id.tv_sa);
    
                tv_name.setText(p.getName());
                tv_phone.setText(p.getPhone());
                tv_sa.setText(p.getSalary());
            }
            return view;
        }
    }

    屏幕上能显示多少个条目,getView方法就会被调用多少次,屏幕向下滑动时,getView会继续被调用,创建更多的View对象显示至屏幕

    条目的缓存

    当条目划出屏幕时,系统会把该条目缓存至内存,当该条目再次进入屏幕,系统在重新调用getView时会把缓存的条目作为convertView参数传入,但是传入的条目不一定是之前被缓存的该条目,即系统有可能在调用getView方法获取第一个条目时,传入任意一个条目的缓存!

    ArrayAdapter

    在条目中显示一个字符串

    String[] objects = new String[]{"AAA","BBB","CCC"};
    ListView lv = (ListView) findViewById(R.id.lv);
    //arg1:指定要填充的布局文件
    //arg2:指定文本显示至哪一个文本框内
    lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_array, R.id.tv_name, objects));

    SimpleAdapter

    可在条目中显示多种数据

    要显示的数据封装在List中,集合的每一个元素存放的是一个条目会显示的数据,因为可能会有多种数据,而集合的泛型只能指定一种数据,所以把数据先存放在Map中,在把Map放入List中

    protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          lv = (ListView)findViewById(R.id.lv);
    
          //把每个条目需要处理的所有数据封装至map中,在把map封装至list中
            //这样就保证了list每个元素都包含了一个条目需要的所有数据
          List<Map<String, Object>> data = new ArrayList<Map<String,Object>>(); 
          Map<String, Object> m1 = new HashMap<String, Object>();
          m1.put("name","AAA");
          m1.put("Photo",R.drawable.a);
          data.add(m1);
    
          Map<String, Object> m2 = new HashMap<String, Object>();
          m2.put("name","BBB");
          m2.put("Photo",R.drawable.b);
          data.add(m2);
    
          Map<String, Object> m3 = new HashMap<String, Object>();
          m3.put("name","CCC");
          m3.put("Photo",R.drawable.c);
          data.add(m3);
    
          lv.setAdapter(new SimpleAdapter(MainActivity.this, data, R.layout.item_listview,
                new String[]{"name","Photo"} ,
                new int[]{R.id.name, R.id.iv}));

    链接: https://pan.baidu.com/s/1R2MVMsnOtrrHuPC2u8gs5Q 密码: y7zq

猜你喜欢

转载自blog.csdn.net/m0_38032942/article/details/81507448