با معرفی پرچمهای راهاندازی ویژگی، خطمشیهای آزمایشی جدیدی وجود دارد که باید از آنها پیروی کنید:
- آزمایشات شما باید هم رفتارهای فعال و هم غیرفعال شده پرچم را پوشش دهد.
- شما باید از مکانیسم های رسمی برای تنظیم مقادیر پرچم در طول آزمایش استفاده کنید.
- تستهای 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_FOOtrueاست وFLAG_BARtrueاست -
FLAG_FOOtrueاست وFLAG_BARfalseاست -
FLAG_FOOfalseاست وFLAG_BARtrueاست -
FLAG_FOOنادرست وFLAG_BARfalseاست
به جای تغییر مستقیم مقادیر پرچم، حاشیه نویسی @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 اصلی خود بازیابی می کند، به طوری که عوارض جانبی روی روش ها و کلاس های تست دیگر نداشته باشد.