Elastos测试框架搭建--测试用例运行流程

来源:互联网 发布:淘宝 无人机 编辑:程序博客网 时间:2024/05/11 10:07

框架的功能:

1. 把测试类的所有接口的测试方法打包成一个epk

2. 通过启动工具启动测试用例的epk,运行包含的测试用例


1.  启动epk(类似apk,启动的时候进入onCreate)

ECode CActivityOne::OnCreate(    /* [in] */ IBundle* savedInstanceState){    Activity::OnCreate(savedInstanceState);    SetContentView(R::layout::main);    sem_init(&g_sem, 0, 0);    SetUp();    String strPackageName;    char szIndex[10];    Int32 index;    AutoPtr<IIntent> intent;    GetIntent((IIntent**)&intent);    intent->GetInt32Extra(String("ARG"), -1, &index);    intent->GetPackage(&strPackageName);    int nLength = sizeof(TestEntry) / sizeof(TestEntry[0]);    if (index <= 0 || index > nLength) {        printf("*ERROR* Invalid testing case number\n");        return -1;    }    sprintf(szIndex , "%d" , index);    char *argv[] = {(char*)(const char *)strPackageName, szIndex};    int argc = 2;    TPINIT;    ActivityParams* pArg = new ActivityParams;    pArg->mActivity = this;    pArg->mIndex = index;    AutoPtr<IHandlerCallback> handlerCallback = new TestcaseCallback((void*)pArg);    CHandler::New((IHandlerCallback*)handlerCallback, TRUE, (IHandler**)&mDefaultHandler);    AutoPtr<TestcaseRunnable> testcaseRunnable;    AutoPtr<IThread> thread;    testcaseRunnable = new TestcaseRunnable((void*)pArg);    CThread::New((IRunnable*)testcaseRunnable, (IThread**)&thread);    thread->Start();    return NOERROR;}


我们来分析下上面的代码:

开始的时候,我们初始化启动的Activity,并且初始化一个信号量,用来处理多线程操作。

sem_init(&g_sem, 0, 0);

接着我们从android的控件通信工具Intent中取出要运行的测试用例编号--index;

    AutoPtr<IIntent> intent;    GetIntent((IIntent**)&intent);    intent->GetInt32Extra(String("ARG"), -1, &index);

计算下有多少个用例要跑,并且判断index是不是在用例号范围内。

    int nLength = sizeof(TestEntry) / sizeof(TestEntry[0]);    if (index <= 0 || index > nLength) {        printf("*ERROR* Invalid testing case number\n");        return -1;    }
上面的TestEntry是一个函数指针数组,如下:

typedef ECode (CActivityOne::*PTestEntry)();PTestEntry TestEntry[] = {    &CActivityOne::Test1,    &CActivityOne::Test2,    &CActivityOne::Test3,    &CActivityOne::Test4,    &CActivityOne::Test5,    &CActivityOne::Test6,    &CActivityOne::Test7,    &CActivityOne::Test8,    &CActivityOne::Test9,    &CActivityOne::Test10,};
这样后续就可以直接通过调用函数指针来调用测试用例了。


继续看OnCreate里面的代码:

    AutoPtr<IHandlerCallback> handlerCallback = new TestcaseCallback((void*)pArg);    CHandler::New((IHandlerCallback*)handlerCallback, TRUE, (IHandler**)&mDefaultHandler);
这里new了一个主线程的handler,主要想法是会测试一些view,那样就可以在另外一个线程里处理好耗时操作后,发个message来更新页面,测试UI接口的正确性。


接着创建一个线程去调用测试用例:

    AutoPtr<TestcaseRunnable> testcaseRunnable;    AutoPtr<IThread> thread;    testcaseRunnable = new TestcaseRunnable((void*)pArg);    CThread::New((IRunnable*)testcaseRunnable, (IThread**)&thread);    thread->Start();

我们再来看看这个线程里做了什么操作:

ECode CActivityOne::TestcaseRunnable::Run(){    ActivityParams* arg = reinterpret_cast<ActivityParams*>(mArg);    CActivityOne* activity = arg->mActivity;    activity->EntryRoutine((void*)arg);    return NOERROR;}
去掉用EntryRoutine方法,那么在这个方法里又干了什么?接着看

void* CActivityOne::EntryRoutine(void *arg){    ActivityParams* paramsArg = reinterpret_cast<ActivityParams*>(arg);    CActivityOne* activity = paramsArg->mActivity;    int index = paramsArg->mIndex;    do {        activity->PostcppCallback(index);        sem_wait(&g_sem);    } while (!s_beQuit);#ifdef AutoExit    TPOK;    activity->Activity::Finish();    KillElastosProcess();#endif    return reinterpret_cast<void*>(0);}

这里调用PostcppCallback去执行,在里面会发送一个message,让主线程去执行对应的测试用例。

同时,当前线程要进入等待状态。这里还有一个问题,大家会看到一个do...while,原先考虑一次性运行所有测试用例,但是由于公司需要根据每条测试用例来关联bug,

因此此处暂时设置s_beQuit = True。


来看看PostcppCallback:

ECode CActivityOne::PostcppCallback(int index){    AutoPtr<IMessage> msg;    Boolean result;    mDefaultHandler->ObtainMessage(102, (IMessage**)&msg);    msg->SetWhat(index);    mDefaultHandler->SendMessage(msg.Get(), &result);    TPAssertTrue("send message failed.\n", result);    return NOERROR;}
这里就看到通过mDefaultHandler向主线程发送message。


那么主线程怎么处理这些消息呢?

ECode CActivityOne::TestcaseCallback::HandleMessage(    /* [in] */ IMessage * msg,    /* [out] */ Boolean * result){    Int32 index;    msg->GetWhat(&index);    ActivityParams* pArg = (ActivityParams*)mArg;    CActivityOne* activity = pArg->mActivity;    (activity->*TestEntry[index-1])();    sem_post(&g_sem);    return NOERROR;}
这里就会通过测试用例的函数指针去调用具体的testcase。

执行完后,信号量加1,使刚刚处于等待状态的线程继续运行。


#ifdef AutoExit    TPOK;    activity->Activity::Finish();    KillElastosProcess();#endif

执行完成后,就退出当前运行的Activity。

finish后没有结束当前进程,纠结,发现android中也没办法。

由于权限的问题,KillElastosProcess也没法杀死系统进程,只好在运行脚本runbat中做处理。

0 0
原创粉丝点击