با معرفی پرچمهای راهاندازی ویژگی، خطمشیهای آزمایشی جدیدی وجود دارد که باید از آنها پیروی کنید:
- آزمایشات شما باید هم رفتارهای فعال و هم غیرفعال شده پرچم را پوشش دهد.
- شما باید از مکانیسم های رسمی برای تنظیم مقادیر پرچم در طول آزمایش استفاده کنید.
- تستهای xTS نباید مقادیر پرچم را در تستها نادیده بگیرند.
بخش بعدی مکانیسمهای رسمی را که باید برای پایبندی به این سیاستها استفاده کنید، ارائه میکند.
کد پرچم گذاری شده خود را تست کنید
سناریوی تست | مکانیزم استفاده شده |
---|---|
آزمایش محلی هنگامی که مقادیر پرچم اغلب تغییر می کند | پل اشکال زدایی اندروید همانطور که در Change a flag's value در زمان اجرا توضیح داده شد |
آزمایش محلی زمانی که مقادیر پرچم اغلب تغییر نمی کند | فایل مقادیر پرچم را همانطور که در مقادیر پرچم راه اندازی ویژگی Set بحث شده است |
آزمایش سرتاسر که در آن مقادیر پرچم تغییر می کند | FeatureFlagTargetPreparer همانطور که در Create end-to-end tests بحث شد |
تست واحد که در آن مقادیر پرچم تغییر می کند | SetFlagsRule با @EnableFlags و @DisableFlags همانطور که در تست های Create unit (جاوا و کاتلین) یا Create unit tests (C و C++) بحث شده است. |
آزمایش سرتاسر یا واحد که در آن مقادیر پرچم نمیتوانند تغییر کنند | CheckFlagsRule همانطور که در ایجاد تست های سرتاسر یا واحد که در آن مقادیر پرچم تغییر نمی کند بحث شد. |
تست های سرتاسری ایجاد کنید
AOSP کلاسی به نام FeatureFlagTargetPreparer
را ارائه میکند که تست سرتاسری را روی یک دستگاه امکانپذیر میکند. این کلاس نادیده گرفتن مقدار پرچم را به عنوان ورودی می پذیرد، آن پرچم ها را در پیکربندی دستگاه ها قبل از اجرای آزمایش تنظیم می کند و پرچم ها را پس از اجرا بازیابی می کند.
میتوانید عملکرد کلاس FeatureFlagTargetPreparer
را در ماژول تست و تنظیمات پیکربندی آزمایشی اعمال کنید.
FeatureFlagTargetPreparer را در پیکربندی ماژول آزمایشی اعمال کنید
برای اعمال FeatureFlagTargetPreparer
در پیکربندی ماژول آزمایشی، FeatureFlagTargetPreparer
و مقدار پرچم را در فایل پیکربندی ماژول تست AndroidTest.xml
اضافه کنید:
<target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer">
<option name="flag-value"
value="permissions/com.android.permission.flags.device_aware_permission_grant=true"/>
<option name="flag-value"
value="virtual_devices/android.companion.virtual.flags.stream_permissions=true"/>
</target_preparer>
کجا:
-
target.preparer class
همیشه رویcom.android.tradefed.targetprep.FeatureFlagTargetPreparer
تنظیم می شود. -
option
لغو پرچم باname
همیشه رویflag-value
وvalue
تنظیم شده رویnamespace/aconfigPackage.flagName=true|false
است.
ماژول های آزمایشی پارامتری را بر اساس وضعیت های پرچم ایجاد کنید
برای ایجاد ماژول های تست پارامتری بر اساس وضعیت های پرچم:
FeatureFlagTargetPreparer
در فایل پیکربندی ماژول تستAndroidTest.xml
قرار دهید:<target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer" >
گزینه های مقدار پرچم را در بخش
test_module_config
یک فایل ساختAndroid.bp
مشخص کنید:android_test { name: "MyTest" ... } test_module_config { name: "MyTestWithMyFlagEnabled", base: "MyTest", ... options: [ {name: "flag-value", value: "telephony/com.android.internal.telephony.flags.oem_enabled_satellite_flag=true"}, ], } test_module_config { name: "MyTestWithMyFlagDisabled", base: "MyTest", ... options: [ {name: "flag-value", value: "telephony/com.android.internal.telephony.flags.carrier_enabled_satellite_flag=true"}, ], }
فیلد
options
حاوی رد پرچمهایی است کهname
همیشه رویflag-value
وvalue
رویnamespace/aconfigPackage.flagName=true|false
تنظیم شده است.
ایجاد تست واحد (جاوا و کاتلین)
این بخش روشی را برای نادیده گرفتن مقادیر پرچم aconfig در سطح کلاس و روش (در هر آزمون) در تستهای جاوا و کاتلین توضیح میدهد.
برای نوشتن تست های واحد خودکار در یک پایگاه کد بزرگ با تعداد زیادی پرچم، این مراحل را دنبال کنید:
- از کلاس
SetFlagsRule
با حاشیه نویسی@EnableFlags
و@DisableFlags
برای آزمایش همه شاخه های کد استفاده کنید. - از روش
SetFlagsRule.ClassRule
برای جلوگیری از باگ های رایج تست استفاده کنید. - از
FlagsParameterization
برای آزمایش کلاس های خود در مجموعه گسترده ای از پیکربندی های پرچم استفاده کنید.
همه شاخه های کد را تست کنید
برای پروژه هایی که از کلاس استاتیک برای دسترسی به پرچم ها استفاده می کنند، کلاس کمکی SetFlagsRule
برای نادیده گرفتن مقادیر پرچم ارائه شده است. قطعه کد زیر نحوه اضافه کردن SetFlagsRule
و فعال کردن چندین پرچم را به طور همزمان نشان می دهد:
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.example.android.aconfig.demo.flags.Flags;
...
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Test
@EnableFlags({Flags.FLAG_FLAG_FOO, Flags.FLAG_FLAG_BAR})
public void test_flag_foo_and_flag_bar_turned_on() {
...
}
کجا:
-
@Rule
یک حاشیه نویسی است که برای افزودن وابستگی flag-JUnit کلاسSetFlagsRule
استفاده می شود. -
SetFlagsRule
یک کلاس کمکی است که برای نادیده گرفتن مقادیر پرچم ارائه شده است. برای اطلاعات در مورد نحوه تعیین مقادیر پیش فرضSetFlagsRule
، به مقادیر پیش فرض دستگاه مراجعه کنید. -
@EnableFlags
یک حاشیه نویسی است که تعداد دلخواه نام پرچم را می پذیرد. هنگام غیرفعال کردن پرچمها، از@DisableFlags
استفاده کنید. شما می توانید این حاشیه نویسی را برای یک متد یا یک کلاس اعمال کنید.
مقادیر پرچم را برای کل فرآیند تست تنظیم کنید، از SetFlagsRule
شروع کنید، که قبل از هر روش تنظیم @Before
-annotated در تست است. زمانی که SetFlagsRule
تمام می شود، مقادیر پرچم به حالت قبلی خود باز می گردند، که پس از هر روش تنظیم @After
-annotated است.
مطمئن شوید که پرچم ها به درستی تنظیم شده اند
همانطور که قبلا ذکر شد، SetFlagsRule
با حاشیه نویسی JUnit @Rule
استفاده می شود، به این معنی که SetFlagsRule
نمی تواند اطمینان حاصل کند که پرچم های شما به درستی در طول سازنده کلاس تست، یا هر روش @BeforeClass
یا @AfterClass
-annotated تنظیم شده است.
برای اطمینان از اینکه فیکسچرهای آزمایشی با مقدار کلاس درست ساخته شده اند، از روش SetFlagsRule.ClassRule
استفاده کنید تا وسایل شما تا زمانی که یک روش تنظیم @Before
-annotated ایجاد نشود:
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import com.example.android.aconfig.demo.flags.Flags;
class ExampleTest {
@ClassRule public static final SetFlagsRule.ClassRule mClassRule = new SetFlagsRule.ClassRule();
@Rule public final SetFlagsRule mSetFlagsRule = mClassRule.createSetFlagsRule();
private DemoClass underTest = new DemoClass();
@Test
@EnableFlags(Flags.FLAG_FLAG_FOO)
public void test_flag_foo_turned_on() {
...
}
}
با افزودن قانون کلاس SetFlagsRule.ClassRule
، test_flag_foo_turned_on
قبل از اجرا زمانی که FLAG_FLAG_FOO
توسط سازنده DemoClass
خوانده می شود، با شکست مواجه می شود.
اگر کل کلاس شما نیاز به یک پرچم فعال دارد، حاشیه نویسی @EnableFlags
را به سطح کلاس (قبل از اعلان کلاس) منتقل کنید. انتقال حاشیه نویسی به سطح کلاس به SetFlagsRule.ClassRule
اجازه می دهد تا مطمئن شود که پرچم به درستی در سازنده کلاس آزمایشی یا در طول هر روش @BeforeClass
یا @AfterClass
-annotated تنظیم شده است.
آزمایشها را روی پیکربندیهای پرچمهای متعدد اجرا کنید
از آنجایی که میتوانید مقادیر پرچم را بر اساس هر آزمون تنظیم کنید، میتوانید از پارامترسازی برای اجرای آزمایشها در چندین پیکربندی پرچم نیز استفاده کنید:
...
import com.example.android.aconfig.demo.flags.Flags;
...
@RunWith(ParameterizedAndroidJunit4::class)
class FooBarTest {
@Parameters(name = "{0}")
public static List<FlagsParameterization> getParams() {
return FlagsParameterization.allCombinationsOf(Flags.FLAG_FOO, Flags.FLAG_BAR);
}
@Rule
public SetFlagsRule mSetFlagsRule;
public FooBarTest(FlagsParameterization flags) {
mSetFlagsRule = new SetFlagsRule(flags);
}
@Test public void fooLogic() {...}
@DisableFlags(Flags.FLAG_BAR)
@Test public void legacyBarLogic() {...}
@EnableFlags(Flags.FLAG_BAR)
@Test public void newBarLogic() {...}
}
توجه داشته باشید که با SetFlagsRule
، اما بدون پارامتر، این کلاس سه تست ( fooLogic
، legacyBarLogic
و newBarLogic
) را اجرا می کند. روش fooLogic
با هر مقداری که مقادیر FLAG_FOO
و FLAG_BAR
روی دستگاه تنظیم شده است اجرا می شود.
هنگامی که پارامترسازی اضافه می شود، متد FlagsParameterization.allCombinationsOf
همه ترکیب های ممکن از پرچم های FLAG_FOO
و FLAG_BAR
را ایجاد می کند:
-
FLAG_FOO
true
است وFLAG_BAR
true
است -
FLAG_FOO
true
است وFLAG_BAR
false
است -
FLAG_FOO
false
است وFLAG_BAR
true
است -
FLAG_FOO
نادرست وFLAG_BAR
false
است
به جای تغییر مستقیم مقادیر پرچم، حاشیه نویسی @DisableFlags
و @EnableFlags
مقادیر پرچم را بر اساس شرایط پارامتر تغییر می دهند. به عنوان مثال، legacyBarLogic
تنها زمانی اجرا می شود که FLAG_BAR
غیرفعال باشد، که در دو ترکیب از چهار ترکیب پرچم رخ می دهد. legacyBarLogic
برای دو ترکیب دیگر نادیده گرفته می شود.
دو روش برای ایجاد پارامترهای پرچم های شما وجود دارد:
FlagsParameterization.allCombinationsOf(String...)
2^n اجرا از هر تست را اجرا می کند. به عنوان مثال، یک پرچم تست های 2x را اجرا می کند یا چهار پرچم تست های 16x را اجرا می کند.FlagsParameterization.progressionOf(String...)
n+1 اجرا از هر تست را اجرا می کند. به عنوان مثال، یک پرچم تست 2x را اجرا می کند و چهار پرچم پرچم 5x را اجرا می کند.
ایجاد تست واحد (C و C++)
AOSP شامل ماکروهای ارزش پرچم برای آزمایشهای C و C++ است که در چارچوب GoogleTest نوشته شدهاند.
در منبع آزمایشی خود، تعاریف ماکرو و کتابخانه های ایجاد شده توسط aconfig را وارد کنید:
#include <flag_macros.h> #include "android_cts_flags.h"
در منبع آزمایشی خود، به جای استفاده از ماکروهای
TEST
وTESTF
برای موارد آزمایشی خود، ازTEST_WITH_FLAGS
وTEST_F_WITH_FLAGS
استفاده کنید:#define TEST_NS android::cts::flags::tests ... TEST_F_WITH_FLAGS( TestFWithFlagsTest, requies_disabled_flag_enabled_skip, REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(TEST_NS, readwrite_enabled_flag)) ) { TestFail(); } ... TEST_F_WITH_FLAGS( TestFWithFlagsTest, multi_flags_for_same_state_skip, REQUIRES_FLAGS_ENABLED( ACONFIG_FLAG(TEST_NS, readwrite_enabled_flag), LEGACY_FLAG(aconfig_flags.cts, TEST_NS, readwrite_disabled_flag) ) ) { TestFail(); } ... TEST_WITH_FLAGS( TestWithFlagsTest, requies_disabled_flag_enabled_skip, REQUIRES_FLAGS_DISABLED( LEGACY_FLAG(aconfig_flags.cts, TEST_NS, readwrite_enabled_flag)) ) { FAIL(); } ... TEST_WITH_FLAGS( TestWithFlagsTest, requies_enabled_flag_enabled_executed, REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_NS, readwrite_enabled_flag)) ) { TestWithFlagsTestHelper::executed_tests.insert( "requies_enabled_flag_enabled_executed"); }
کجا:
- ماکروهای
TEST_WITH_FLAGS
وTEST_F_WITH_FLAGS
به جای ماکروهایTEST
وTEST_F
استفاده میشوند. -
REQUIRES_FLAGS_ENABLED
مجموعهای از پرچمهای انتشار ویژگی را تعریف میکند که باید شرایط فعال را داشته باشند. می توانید این پرچم ها را در ماکروهایACONFIG_FLAG
یاLEGACY_FLAG
بنویسید. -
REQUIRES_FLAGS_DISABLED
مجموعهای از پرچمهای ویژگی را تعریف میکند که باید شرایط غیرفعال را داشته باشند. می توانید این پرچم ها را در ماکروهایACONFIG_FLAG
یاLEGACY_FLAG
بنویسید. -
ACONFIG_FLAG (TEST_NS, readwrite_enabled_flag)
یک ماکرو است که برای پرچم های تعریف شده در فایل های aconfig استفاده می شود. این ماکرو یک فضای نام (TEST_NS
) و یک نام پرچم (readwrite_enabled_flag
) را می پذیرد. -
LEGACY_FLAG(aconfig_flags.cts, TEST_NS, readwrite_disabled_flag)
یک ماکرو است که برای پرچمهایی که به طور پیشفرض در پیکربندی دستگاه تنظیم شدهاند استفاده میشود.
- ماکروهای
در فایل ساخت
Android.bp
خود، کتابخانه های ایجاد شده توسط aconfig و کتابخانه های ماکرو مربوطه را به عنوان وابستگی آزمایشی اضافه کنید:cc_test { name: "FlagMacrosTests", srcs: ["src/FlagMacrosTests.cpp"], static_libs: [ "libgtest", "libflagtest", "my_aconfig_lib", ], shared_libs: [ "libbase", "server_configurable_flags", ], test_suites: ["general-tests"], ... }
با این دستور تست ها را به صورت محلی اجرا کنید:
atest FlagMacrosTests
اگر پرچم
my_namespace.android.myflag.tests.my_flag
غیرفعال باشد، نتیجه آزمایش به صورت زیر است:[1/2] MyTest#test1: IGNORED (0ms) [2/2] MyTestF#test2: PASSED (0ms)
اگر پرچم
my_namespace.android.myflag.tests.my_flag
فعال باشد، نتیجه آزمایش به صورت زیر است:[1/2] MyTest#test1: PASSED (0ms) [2/2] MyTestF#test2: IGNORED (0ms)
در جایی که مقادیر پرچم تغییر نمیکند، آزمایشهای سرتاسر یا واحد ایجاد کنید
برای موارد آزمایشی که نمیتوانید پرچمها را لغو کنید و فقط در صورتی میتوانید آزمایشها را فیلتر کنید که بر اساس وضعیت پرچم فعلی باشند، از قانون CheckFlagsRule
با حاشیهنویسی RequiresFlagsEnabled
و RequiresFlagsDisabled
استفاده کنید.
مراحل زیر به شما نشان میدهد که چگونه میتوانید یک تست سرتاسر یا واحد را ایجاد و اجرا کنید که در آن مقادیر پرچم قابل لغو نیستند:
در کد تست خود، از
CheckFlagsRule
برای اعمال فیلترینگ تست استفاده کنید. همچنین، از حاشیه نویسی جاواRequiresFlagsEnabled
وRequiredFlagsDisabled
برای تعیین الزامات پرچم برای آزمون خود استفاده کنید.تست سمت دستگاه از کلاس
DeviceFlagsValueProvider
استفاده می کند:@RunWith(JUnit4.class) public final class FlagAnnotationTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @Test @RequiresFlagsEnabled(Flags.FLAG_FLAG_NAME_1) public void test1() {} @Test @RequiresFlagsDisabled(Flags.FLAG_FLAG_NAME_1) public void test2() {} }
تست سمت میزبان از کلاس
HostFlagsValueProvider
استفاده می کند:@RunWith(DeviceJUnit4ClassRunner.class) public final class FlagAnnotationTest extends BaseHostJUnit4Test { @Rule public final CheckFlagsRule mCheckFlagsRule = HostFlagsValueProvider.createCheckFlagsRule(this::getDevice); @Test @RequiresFlagsEnabled(Flags.FLAG_FLAG_NAME_1) public void test1() {} @Test @RequiresFlagsDisabled(Flags.FLAG_FLAG_NAME_1) public void test2() {} }
کتابخانه های
jflag-unit
و aconfig-generated را برای آزمایش خود به بخشstatic_libs
فایل ساخت اضافه کنید:android_test { name: "FlagAnnotationTests", srcs: ["*.java"], static_libs: [ "androidx.test.rules", "my_aconfig_lib", "flag-junit", "platform-test-annotations", ], test_suites: ["general-tests"], }
برای اجرای تست به صورت محلی از دستور زیر استفاده کنید:
atest FlagAnnotationTests
اگر پرچم
Flags.FLAG_FLAG_NAME_1
غیرفعال باشد، نتیجه آزمایش این است:[1/2] com.cts.flags.FlagAnnotationTest#test1: ASSUMPTION_FAILED (10ms) [2/2] com.cts.flags.FlagAnnotationTest#test2: PASSED (2ms)
در غیر این صورت نتیجه آزمایش این است:
[1/2] com.cts.flags.FlagAnnotationTest#test1: PASSED (2ms) [2/2] com.cts.flags.FlagAnnotationTest#test2: ASSUMPTION_FAILED (10ms)
مقادیر پیش فرض دستگاه
SetFlagsRule
اولیه از مقادیر پرچم از دستگاه استفاده می کند. اگر مقدار پرچم روی دستگاه، مانند adb، نادیده گرفته نشود، مقدار پیشفرض همان پیکربندی انتشار بیلد است. اگر مقدار روی دستگاه لغو شده باشد، SetFlagsRule
از مقدار override به عنوان پیش فرض استفاده می کند.
اگر همان آزمایش تحت پیکربندی های مختلف انتشار اجرا شود، مقدار پرچم هایی که به طور صریح با SetFlagsRule
تنظیم نشده اند، می تواند متفاوت باشد.
پس از هر آزمایش، SetFlagsRule
نمونه FeatureFlags
در Flags
را به FeatureFlagsImpl
اصلی خود بازیابی می کند، به طوری که عوارض جانبی روی روش ها و کلاس های تست دیگر نداشته باشد.