इसमें टेस्ट मैपिंग के बारे में कम शब्दों में जानकारी दी गई है. साथ ही, Android Open Source Project (AOSP) में टेस्ट कॉन्फ़िगर करने का तरीका बताया गया है.
टेस्ट मैपिंग के बारे में जानकारी
टेस्ट मैपिंग, Gerrit पर आधारित एक तरीका है. इसकी मदद से डेवलपर, Android के सोर्स ट्री में सीधे तौर पर, सबमिट करने से पहले और सबमिट करने के बाद टेस्ट करने के नियम बना सकते हैं. साथ ही, टेस्ट किए जाने वाले डिवाइसों और ब्रांच के फ़ैसले, टेस्ट इन्फ़्रास्ट्रक्चर पर छोड़ सकते हैं.
मैपिंग की परिभाषाओं की जांच करने वाली फ़ाइलें, TEST_MAPPING
नाम वाली JSON फ़ाइलें होती हैं. इन्हें किसी भी सोर्स डायरेक्ट्री में रखा जा सकता है.
Atest, TEST_MAPPING
फ़ाइलों का इस्तेमाल करके, इससे जुड़ी डायरेक्ट्री में सबमिट करने से पहले की जाने वाली जांच कर सकता है. टेस्ट मैपिंग की मदद से, Android सोर्स ट्री में कम से कम बदलाव करके, टेस्ट के एक ही सेट को सबमिट करने से पहले की जाने वाली जांचों में जोड़ा जा सकता है.
ये उदाहरण देखें:
टेस्ट मैपिंग, टेस्ट को लागू करने और नतीजों की रिपोर्टिंग के लिए, ट्रेड फ़ेडरेशन (टीएफ़) टेस्ट हार्नेस पर निर्भर करती है.
टेस्ट ग्रुप तय करना
टेस्ट ग्रुप की मदद से, मैपिंग ग्रुप के टेस्ट की जांच करें. टेस्ट ग्रुप का नाम कोई भी स्ट्रिंग हो सकता है. उदाहरण के लिए, बदलावों की पुष्टि करते समय किए जाने वाले टेस्ट के ग्रुप का नाम presubmit हो सकता है. साथ ही, postsubmit ऐसे टेस्ट हो सकते हैं जिनका इस्तेमाल, बदलावों को मर्ज करने के बाद बिल्ड की पुष्टि करने के लिए किया जाता है.
पैकेज बनाने की स्क्रिप्ट के नियम
किसी बिल्ड के लिए टेस्ट मॉड्यूल चलाने के लिए, Trade Federation test harness को इन मॉड्यूल में से किसी एक के लिए, test_suites
को Soong पर सेट करना होगा या LOCAL_COMPATIBILITY_SUITE
को Make पर सेट करना होगा:
general-tests
उन टेस्ट के लिए है जो डिवाइस की खास सुविधाओं पर निर्भर नहीं होते. जैसे, वेंडर के हिसाब से हार्डवेयर, जो ज़्यादातर डिवाइसों में नहीं होता. ज़्यादातर टेस्टgeneral-tests
सुइट में होने चाहिए. भले ही, वे किसी एक एबीआई, बिटनेस या हार्डवेयर की सुविधाओं, जैसे कि HWASan के लिए खास तौर पर बनाए गए हों. हर एबीआई के लिए एक अलगtest_suites
टारगेट होता है. भले ही, उन्हें किसी डिवाइस पर चलाना हो.device-tests
ऐसे टेस्ट के लिए होता है जो डिवाइस की खास सुविधाओं पर निर्भर करते हैं. आम तौर पर, ये टेस्टvendor/
में मिलते हैं. डिवाइस के हिसाब से का मतलब सिर्फ़ उन सुविधाओं से है जो किसी डिवाइस के लिए यूनीक होती हैं. इसलिए, यह JUnit टेस्ट के साथ-साथ GTest टेस्ट पर भी लागू होता है. GTest टेस्ट को आम तौर परgeneral-tests
के तौर पर मार्क किया जाना चाहिए, भले ही वे ABI के हिसाब से हों.
उदाहरण:
Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests
टेस्ट सुइट में टेस्ट चलाने के लिए, उन्हें कॉन्फ़िगर करना
किसी टेस्ट सुइट में टेस्ट चलाने के लिए, टेस्ट में ये चीज़ें होनी चाहिए:
- कोई बिल्ड प्रोवाइडर नहीं होना चाहिए.
- टेस्ट पूरा होने के बाद, इसे साफ़ करना ज़रूरी है. उदाहरण के लिए, टेस्ट के दौरान जनरेट हुई किसी भी अस्थायी फ़ाइल को मिटाना.
- सिस्टम की सेटिंग को डिफ़ॉल्ट या मूल वैल्यू पर बदलना ज़रूरी है.
यह नहीं मान लेना चाहिए कि डिवाइस किसी खास स्थिति में है. उदाहरण के लिए, रूट करने के लिए तैयार है. ज़्यादातर टेस्ट चलाने के लिए, रूट विशेषाधिकार की ज़रूरत नहीं होती. अगर किसी टेस्ट के लिए रूट की ज़रूरत है, तो उसे
AndroidTest.xml
मेंRootTargetPreparer
के साथ यह जानकारी देनी चाहिए. जैसे, यहां दिए गए उदाहरण में बताया गया है:<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
टेस्ट मैपिंग फ़ाइलें बनाना
जिस डायरेक्ट्री के लिए टेस्ट कवरेज की ज़रूरत है उसके लिए, उदाहरण के जैसा TEST_MAPPING
JSON फ़ाइल जोड़ें. इन नियमों से यह पक्का किया जाता है कि जब उस डायरेक्ट्री या उसकी किसी भी सबडायरेक्ट्री में कोई फ़ाइल बदली जाती है, तो प्रीसबमिट जांच में टेस्ट रन होते हैं.
उदाहरण देखें
यहां TEST_MAPPING
फ़ाइल का एक सैंपल दिया गया है. यह JSON फ़ॉर्मैट में है, लेकिन इसमें टिप्पणियां शामिल की जा सकती हैं:
{
"presubmit": [
// JUnit test with options and file patterns.
{
"name": "CtsWindowManagerDeviceTestCases",
"options": [
{
"include-annotation": "android.platform.test.annotations.RequiresDevice"
}
],
"file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
},
// Device-side GTest with options.
{
"name" : "hello_world_test",
"options": [
{
"native-test-flag": "\"servicename1 servicename2\""
},
{
"native-test-timeout": "6000"
}
]
}
// Host-side GTest.
{
"name" : "net_test_avrcp",
"host" : true
}
],
"postsubmit": [
{
"name": "CtsDeqpTestCases",
"options": [
{
// Use regex in include-filter which is supported in AndroidJUnitTest
"include-filter": "dEQP-EGL.functional.color_clears.*"
}
]
}
],
"imports": [
{
"path": "frameworks/base/services/core/java/com/android/server/am"
}
]
}
एट्रिब्यूट सेट करना
उदाहरण में, presubmit
और postsubmit
, हर टेस्ट ग्रुप के नाम हैं. टेस्ट ग्रुप के बारे में ज़्यादा जानकारी के लिए, टेस्ट ग्रुप तय करना लेख पढ़ें.
name
एट्रिब्यूट की वैल्यू में, टेस्ट मॉड्यूल या Trade Federation इंटिग्रेशन टेस्ट के नाम को सेट किया जा सकता है. जैसे, टेस्ट एक्सएमएल फ़ाइल का रिसॉर्स पाथ uiautomator/uiautomator-demo
. ध्यान दें कि name
फ़ील्ड में, क्लास name
या टेस्ट के तरीके name
का इस्तेमाल नहीं किया जा सकता. जांचों की संख्या कम करने के लिए, include-filter
जैसे विकल्पों का इस्तेमाल करें. include-filter
इस्तेमाल का उदाहरण देखें.
टेस्ट की host
सेटिंग से पता चलता है कि टेस्ट, डिवाइस के बिना होस्ट पर चल रहा है या नहीं. डिफ़ॉल्ट वैल्यू false
है. इसका मतलब है कि टेस्ट को चलाने के लिए डिवाइस की ज़रूरत होती है. इन टेस्ट टाइप का इस्तेमाल किया जा सकता है:
GTest बाइनरी के लिए HostGTest
और JUnit टेस्ट के लिए HostTest
.
file_patterns
एट्रिब्यूट की मदद से, किसी भी सोर्स कोड फ़ाइल के रिलेटिव पाथ को मैच करने के लिए, रेगुलर एक्सप्रेशन स्ट्रिंग की सूची सेट की जा सकती है. यह सूची, TEST_MAPPING
फ़ाइल वाली डायरेक्ट्री के हिसाब से होती है. उदाहरण में, टेस्ट CtsWindowManagerDeviceTestCases
सिर्फ़ तब चलता है, जब Java फ़ाइल Window
या Activity
से शुरू होती है. यह फ़ाइल, TEST_MAPPING
फ़ाइल या उसकी किसी भी सबडायरेक्ट्री में मौजूद होती है. बैकस्लैश (\) को एस्केप करने की ज़रूरत होती है, क्योंकि वे JSON फ़ाइल में होते हैं.
imports
एट्रिब्यूट की मदद से, कॉन्टेंट को कॉपी किए बिना अन्य TEST_MAPPING
फ़ाइलों में टेस्ट शामिल किए जा सकते हैं. इंपोर्ट किए गए पाथ की पैरंट डायरेक्ट्री में मौजूद TEST_MAPPING
फ़ाइलें भी शामिल की जाती हैं. टेस्ट मैपिंग की मदद से, नेस्ट किए गए इंपोर्ट किए जा सकते हैं. इसका मतलब है कि दो TEST_MAPPING
फ़ाइलें एक-दूसरे को इंपोर्ट कर सकती हैं. साथ ही, टेस्ट मैपिंग में शामिल किए गए टेस्ट को मर्ज किया जा सकता है.
options
एट्रिब्यूट में, Tradefed के कमांड लाइन के अतिरिक्त विकल्प शामिल होते हैं.
किसी टेस्ट के लिए उपलब्ध सभी विकल्पों की पूरी सूची पाने के लिए, यह कमांड चलाएं:
tradefed.sh run commandAndExit [test_module] --help
विकल्पों के काम करने के तरीके के बारे में ज़्यादा जानने के लिए, Tradefed में विकल्प हैंडल करना लेख पढ़ें.
Atest का इस्तेमाल करके टेस्ट चलाना
सबमिट करने से पहले की जाने वाली जांच के नियमों को स्थानीय तौर पर लागू करने के लिए:
- उस डायरेक्ट्री पर जाएं जिसमें
TEST_MAPPING
फ़ाइल मौजूद है. यह निर्देश चलाएं:
atest
मौजूदा डायरेक्ट्री और इसकी पैरंट डायरेक्ट्री की TEST_MAPPING
फ़ाइलों में कॉन्फ़िगर किए गए सभी प्रीसबमिट टेस्ट चलाए जाते हैं. Atest, सबमिट करने से पहले किए जाने वाले दो टेस्ट (A और B) का पता लगाता है और उन्हें चलाता है.
TEST_MAPPING
फ़ाइलों में, प्रीसबमिट टेस्ट चलाने का यह सबसे आसान तरीका है. ये फ़ाइलें, मौजूदा वर्किंग डायरेक्ट्री (सीडब्ल्यूडी) और पैरंट डायरेक्ट्री में मौजूद होती हैं. Atest, CWD और इसके सभी पैरंट डायरेक्ट्री में मौजूद TEST_MAPPING
फ़ाइल का पता लगाता है और उसका इस्तेमाल करता है.
सोर्स कोड को स्ट्रक्चर करना
इस उदाहरण में बताया गया है कि सोर्स ट्री में मौजूद TEST_MAPPING
फ़ाइलों को कैसे कॉन्फ़िगर किया जा सकता है:
src
├── project_1
│ └── TEST_MAPPING
├── project_2
│ └── TEST_MAPPING
└── TEST_MAPPING
src/TEST_MAPPING
का कॉन्टेंट:
{
"presubmit": [
{
"name": "A"
}
]
}
src/project_1/TEST_MAPPING
का कॉन्टेंट:
{
"presubmit": [
{
"name": "B"
}
],
"postsubmit": [
{
"name": "C"
}
],
"other_group": [
{
"name": "X"
}
]}
src/project_2/TEST_MAPPING
का कॉन्टेंट:
{
"presubmit": [
{
"name": "D"
}
],
"import": [
{
"path": "src/project_1"
}
]}
टारगेट डायरेक्ट्री तय करना
उस डायरेक्ट्री में मौजूद TEST_MAPPING
फ़ाइलों में टेस्ट चलाने के लिए, टारगेट डायरेक्ट्री तय की जा सकती है. नीचे दी गई कमांड, दो टेस्ट (A, B) चलाती है:
atest --test-mapping src/project_1
पोस्टसबमिट टेस्ट के नियम लागू करना
इस कमांड का इस्तेमाल, src_path
में TEST_MAPPING
में तय किए गए पोस्टसबमिट टेस्ट के नियमों को चलाने के लिए भी किया जा सकता है. यह कमांड, src_path
(डिफ़ॉल्ट रूप से CWD) और इसकी पैरंट डायरेक्ट्री में काम करती है:
atest [--test-mapping] [src_path]:postsubmit
सिर्फ़ ऐसे टेस्ट चलाएं जिनके लिए डिवाइस की ज़रूरत नहीं होती
Atest के लिए, --host
विकल्प का इस्तेमाल किया जा सकता है. इससे सिर्फ़ वे टेस्ट चलाए जा सकते हैं जिन्हें होस्ट के हिसाब से कॉन्फ़िगर किया गया है और जिनके लिए डिवाइस की ज़रूरत नहीं होती. इस विकल्प के बिना, Atest दोनों टेस्ट चलाता है. ऐसे टेस्ट जिनके लिए डिवाइस की ज़रूरत होती है और ऐसे टेस्ट जो किसी ऐसे होस्ट पर चलते हैं जिसके लिए डिवाइस की ज़रूरत नहीं होती. टेस्ट दो अलग-अलग सुइट में चलाए जाते हैं:
atest [--test-mapping] --host
टेस्ट ग्रुप की पहचान करना
Atest कमांड में टेस्ट ग्रुप तय किए जा सकते हैं. नीचे दी गई कमांड, src/project_1
डायरेक्ट्री में मौजूद फ़ाइलों से जुड़े सभी postsubmit
टेस्ट चलाती है. इस डायरेक्ट्री में सिर्फ़ एक टेस्ट (C) शामिल है.
इसके अलावा, ग्रुप से जुड़े सभी टेस्ट चलाने के लिए, :all
का इस्तेमाल किया जा सकता है. नीचे दी गई कमांड से चार टेस्ट (A, B, C, X) चलाए जाते हैं:
atest --test-mapping src/project_1:all
सबडायरेक्ट्री शामिल करें
डिफ़ॉल्ट रूप से, TEST_MAPPING
में Atest के साथ टेस्ट चलाने पर, सिर्फ़ उन प्रीसबमिट टेस्ट को चलाया जाता है जिन्हें CWD (या दी गई डायरेक्ट्री) और उसकी पैरंट डायरेक्ट्री में मौजूद TEST_MAPPING
फ़ाइल में कॉन्फ़िगर किया गया है. अगर आपको सबडाइरेक्ट्री में मौजूद सभी TEST_MAPPING
फ़ाइलों में टेस्ट चलाने हैं, तो --include-subdir
विकल्प का इस्तेमाल करके, Atest को उन टेस्ट को भी शामिल करने के लिए मजबूर करें.
atest --include-subdir
--include-subdir
विकल्प के बिना, Atest सिर्फ़ टेस्ट A को चलाता है. --include-subdir
विकल्प की मदद से, Atest दो टेस्ट (A, B) चलाता है.
लाइन के लेवल पर टिप्पणी करने की सुविधा उपलब्ध है
TEST_MAPPING
फ़ाइल में, सेटिंग के बारे में जानकारी देने के लिए, लाइन-लेवल //
फ़ॉर्मैट वाली टिप्पणी जोड़ी जा सकती है.
ATest और Trade Federation, टिप्पणियों के बिना TEST_MAPPING
को मान्य JSON फ़ॉर्मैट में प्रीप्रोसेस करते हैं. JSON फ़ाइल को साफ़-सुथरा रखने के लिए, सिर्फ़ लाइन-लेवल //
फ़ॉर्मैट वाली टिप्पणी का इस्तेमाल किया जा सकता है.
उदाहरण:
{
// For presubmit test group.
"presubmit": [
{
// Run test on module A.
"name": "A"
}
]
}