【C/C++开发及测试】Elastos测试框架搭建--测试用例运行流程

框架的功能:

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值