推荐轻量级Android DAO单元测试框架——YuiHatano

image

YuiHatano介绍

https://github.com/kkmike999/YuiHatano

YuiHatano是一款轻量级DAO单元测试框架,开发者可以通过此框架,在Android Studio运行SQLiteDatabase、SharedPreference单元测试。

YuiHatano支持原生SQLiteDatabase操作及GreenDAO、Afinal、XUtils、DbFlow第三方库。

在悦跑圈实践

笔者在悦跑圈Android 2.10版本后使用了YuiHatano,暂时没发现问题,配置方面也很方便。

关于命名

有道云翻译:YuiHatano - 波多野**

(鉴于儿童不宜,部分翻译打码。)


吐槽robolectric

相信很多同学,都用过或者听闻过 Robolectric,一款Android单元测试框架。无可否认,Robolectric称得上是Android业界最权威的单元测试框架之一。Google推荐的AndroidJUnitRunner、espresso,跑测试都要运行在真机或模拟器上,而robolectric可以在pc上跑ui测试,无疑大大地提高运行速度。

robolectric下载依赖慢、配置麻烦

但是,刚上手robolectric的小白,特别是天朝的同学,都会说上百次Fu*k。因为,robolectric在运行时,会去https://oss.sonatype.org下载几十M的库,最可怕的是,https://oss.sonatype.org很慢很慢,第一次运行你可以去吃个中午饭,喝个下午茶,回来也未必下载完。笔者已给出解决方案:《加速Robolectric下载依赖库》

还有,robolectric有各种配置,偶尔还有配置没改,突然跑不起来,说找不到**文件等bug(不知道3.3还有没存在这问题)。遇到这种情况,开发者只能花半天找问题或改配置。

尽管robolectric第一次hello world比较头疼,配置繁琐,文档较少,ui测试功能有限,但确实是一种不错的在本地运行的单元测试方案。

robolectric还是慢

虽然,robolectric在本地运行,比编译单元测试,扔上真机跑的AndroidJunitRunner、espresso要快;但是无论你跑多简单的test case,它每次运行都要花上几秒加载&解析资源等,如果项目比较复杂,甚至耗时十几秒(笔者亲测)。

一个简单的test case:

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class RoboTest {

    @Test
    public void test() throws Exception {
        System.out.println("first robo test");
    }
}

居然耗费10s!!


更好的方案——YuiHatano

其实,YuiHatano是笔者撸的一个框架,目的是解决robolectric运行慢问题。YuiHatano不存在robolectric一运行就加载资源问题,也更有效地输出执行的sqlite语句。

YuiHatano仅仅提供DAO测试功能,如果你要测ui,请选其他方案。

Getting Started

Building with Gradle

repositories {
    maven { url "https://dl.bintray.com/kkmike999/maven" }
}

dependencies {
    testImplementation('net.yui:YuiHatano:1.1.4') {
        exclude group: 'com.android.support'
    }
}

Configuration

在Android Studio操作栏,Run->EditConfigurations,双击Defaults,选择Android JUnit窗口,找到Working directory参数栏,点击最右边的...选择MODULE_DIR。

写第一个测试

SQLiteDatabase

public class SQLiteDatabaseTest extends YuiCase {

    SQLiteDatabase db;

    @Before
    public void setUp() throws Exception {
        // 使用YuiHatano提供的Context,获取SQLiteDatabase实例
        db = getContext().openOrCreateDatabase("build/test.db", 0, null);
    }

    @Test
    public void testCreateTable() {
        String sql = "CREATE TABLE person (id INTEGER, name VARCHAR)";

        db.execSQL(sql);
    }
}

测试用例执行SQL语句CREATE TABLE person (id INTEGER, name VARCHAR),先创建临时sqlite数据库,再临时创建person表。每个测试方法完成后,临时数据库都会被删除,因此不能在testA()创建表,testB()使用这张表。

执行结果:

结果显示,只用了1秒多,比robolectric快几十倍。输出的SQL语句是真实执行在sqlite数据库的。

GreenDAO

先按 GreenDAO 官方文档,配置好gradle等。

User

@Entity
public class User {

    // 不能用int
    @Id(autoincrement = true)
    private Long id;

    @Unique
    private int uid;

    private String name;

    public User(int uid, String name) {
        this.uid = uid;
        this.name = name;
    }
}

单元测试

public class GreenDAOTest extends GreenDAOCase {

    private DaoSession mDaoSession;
    private UserDao    mUserDAO;

    @BeforeClass
    public static void beforeClass() {
        DebugHook.setDebug(true);
    }

    @Before
    public void setUp() throws Exception {
        Context context = getContext();

        // 创建数据库 build/test.db,数据库名就是路径
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, "test.db", null);
        // 获取可写数据库
        SQLiteDatabase db = helper.getWritableDatabase();

        // 获取数据库对象
        DaoMaster daoMaster = new DaoMaster(db);
        // 获取Dao对象管理者
        mDaoSession = daoMaster.newSession();

        mUserDAO = mDaoSession.getUserDao();
    }

    @Test
    public void testInsert() {
        int    uid  = 1;
        String name = "键盘男";
    
        User user = new User(uid, name);

        mUserDAO.insert(user);

        List<User> users = mUserDAO.loadAll();

        Assert.assertEquals(1, users.size());

        Assert.assertEquals(1, users.get(0).getUid());
        Assert.assertEquals("键盘男", users.get(0).getName());
    }
}

执行结果:

输出结果,显示SQL语句CREATE TABLE "USER"...INSERT INTO "USER"SELECT...,上面的例子说了,YuiHatano输出的SQL都是真实执行的。

AFinal、XUtils、DbFlow

YuiHatano还支持这几款框架,本文不详细说明,在 Github 有详细用例。


Native方法测试

(目前仅支持MacOS)

示例目录结构:

./app/
└── src
    ├── main
    │   ├── cpp
    │   │   ├── CMakeLists.txt
    │   │   └── jni.cpp
    │   ├── java
    │   │   └── net
    │   │       └── yui
    │   │           └── app
    │   │               ├── JNI.java
    └── test
        └── java
            └── net
                └── yui
                    └── app
                        ├── jni
                        │   └── TestJNI.java

含有native方法的JNI:

public class JNI {
    public native int add(int a, int b);
}

测试用例继承JNICase,其他代码照常:

public class TestJNI extends JNICase {

    static {
        System.loadLibrary("jni");
    }

    @Test
    public void testJNI() {
        JNI jni = new JNI();
        Assert.assertEquals(2, jni.add(1, 1));
    }
}

不完善的地方

笔者还未试过GreenDAO等联表查询,不知道YuiHatano对这方面是否有bug. 希望同学们遇到bug,在github issues上提出。


推荐阅读:《Android 面试指南》

关于作者

我是键盘男。
在广州生活,悦跑圈Android工程师,猥琐文艺码农。每天谋划砍死产品经理。喜欢科学、历史,玩玩投资,偶尔旅行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容