【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中做處理。

發佈了49 篇原創文章 · 獲贊 15 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章