udacity android 實踐筆記: lesson 4 part b

來源:互聯網
上載者:User

標籤:android   單元測試   android-studio   

udacity android 實踐筆記: lesson 4 part b

乾貨店打雜的 /titer1 /Archimedes
出處:https://code.csdn.net/titer1
聯絡:1307316一九六八(簡訊最佳)
聲明:本文採用以下協議進行授權: 自由轉載-非商用-非衍生-保持署名|Creative Commons BY-NC-ND 3.0 ,轉載請註明作者及出處。
tips:https://code.csdn.net/titer1/pat_aha/blob/master/Markdown/android/

摘要

  • 完全展示content provider添加的過程
  • 動態展示android單元測試的過程
    動圖出沒喔!o(^▽^)o,動圖在最後
overviw 圖

還是老圖,(create / insert /query)

下面 我們開始 content provider的學習

複習四大 組件content providerservicebroadcast provideractvity 
本章 overview

4.07 init code for content provider


- 測試打樁函數就佔了大半
- 然後傳統的函數裡面修改了 weatherContrace
- 增加了 weatherProvider
- 修改了 fetchweatherTask函數,代碼的來源是
從 forececastFragment代碼拆解出來的。
- 除了修改weatherContrace,其他檔案都是 新增加的

關鍵詞 uri

weatherContract裡面增加的最多就是產生uri的函數

    /* Inner class that defines the table contents of the location table */    public static final class LocationEntry implements BaseColumns {    ...        public static Uri buildLocationUri(long id) {            return ContentUris.withAppendedId(CONTENT_URI, id);        }    }    ===
    /* Inner class that defines the table contents of the weather table */    public static final class WeatherEntry implements BaseColumns {        ...        public static Uri buildWeatherLocation(String locationSetting) {            return null;        }        public static Uri buildWeatherLocationWithStartDate(                String locationSetting, long startDate) {            long normalizedDate = normalizeDate(startDate);            return CONTENT_URI.buildUpon().appendPath(locationSetting)                    .appendQueryParameter(COLUMN_DATE, Long.toString(normalizedDate)).build();        }        public static Uri buildWeatherLocationWithDate(String locationSetting, long date) {            return CONTENT_URI.buildUpon().appendPath(locationSetting)                    .appendPath(Long.toString(normalizeDate(date))).build();        }        public static String getLocationSettingFromUri(Uri uri) {            return uri.getPathSegments().get(1);        }        public static long getDateFromUri(Uri uri) {            return Long.parseLong(uri.getPathSegments().get(2));        }        public static long getStartDateFromUri(Uri uri) {            String dateString = uri.getQueryParameter(COLUMN_DATE);            if (null != dateString && dateString.length() > 0)                return Long.parseLong(dateString);            else                return 0;        }    }}
4.08 uri location with weather

僅2處更新

1/2 weatherContract
        /*            Student: This is the buildWeatherLocation function you filled in.         */        public static Uri buildWeatherLocation(String locationSetting) {            return CONTENT_URI.buildUpon().appendPath(locationSetting).build();//上一版本這裡返回空值        }

##2/2 test

僅僅開啟 這裡的注釋
“` java
/*
Students: This is NOT a complete test for the WeatherContract — just for the functions
that we expect you to write.
*/
public class TestWeatherContract extends AndroidTestCase {

// intentionally includes a slash to make sure Uri is getting quoted correctlyprivate static final String TEST_WEATHER_LOCATION = "/North Pole";private static final long TEST_WEATHER_DATE = 1419033600L;  // December 20th, 2014/*    Students: Uncomment this out to test your weather location function. */public void testBuildWeatherLocation() {    Uri locationUri = WeatherContract.WeatherEntry.buildWeatherLocation(TEST_WEATHER_LOCATION);    assertNotNull("Error: Null Uri returned.  You must fill-in buildWeatherLocation in " +                    "WeatherContract.",            locationUri);    assertEquals("Error: Weather location not properly appended to the end of the Uri",            TEST_WEATHER_LOCATION, locationUri.getLastPathSegment());    assertEquals("Error: Weather location Uri doesn‘t match our expected result",            locationUri.toString(),            "content://com.example.android.sunshine.app/weather/%2FNorth%20Pole");}

}
“`

4.09 write uri matcher1/2 weatherProvider

這是架構裡面的代碼,更新一處

    /*        Students: Here is where you need to create the UriMatcher. This UriMatcher will        match each URI to the WEATHER, WEATHER_WITH_LOCATION, WEATHER_WITH_LOCATION_AND_DATE,        and LOCATION integer constants defined above.  You can test this by uncommenting the        testUriMatcher test within TestUriMatcher.     */    static UriMatcher buildUriMatcher() {        // I know what you‘re thinking.  Why create a UriMatcher when you can use regular        // expressions instead?  Because you‘re not crazy, that‘s why.        // All paths added to the UriMatcher have a corresponding code to return when a match is        // found.  The code passed into the constructor represents the code to return for the root        // URI.  It‘s common to use NO_MATCH as the code for this case.        final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);        final String authority = WeatherContract.CONTENT_AUTHORITY;        // For each type of URI you want to add, create a corresponding code.        matcher.addURI(authority, WeatherContract.PATH_WEATHER, WEATHER);        matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*", WEATHER_WITH_LOCATION);        matcher.addURI(authority, WeatherContract.PATH_WEATHER + "/*/#", WEATHER_WITH_LOCATION_AND_DATE);        matcher.addURI(authority, WeatherContract.PATH_LOCATION, LOCATION);        return matcher;    }
2/2 test

依然是已經寫好的測試代碼架構,這裡僅僅開啟注釋

public class TestUriMatcher extends AndroidTestCase {...    /*        Students: This function tests that your UriMatcher returns the correct integer value        for each of the Uri types that our ContentProvider can handle.  Uncomment this when you are        ready to test your UriMatcher.     */    public void testUriMatcher() {        UriMatcher testMatcher = WeatherProvider.buildUriMatcher();        assertEquals("Error: The WEATHER URI was matched incorrectly.",                testMatcher.match(TEST_WEATHER_DIR), WeatherProvider.WEATHER);        assertEquals("Error: The WEATHER WITH LOCATION URI was matched incorrectly.",                testMatcher.match(TEST_WEATHER_WITH_LOCATION_DIR), WeatherProvider.WEATHER_WITH_LOCATION);        assertEquals("Error: The WEATHER WITH LOCATION AND DATE URI was matched incorrectly.",                testMatcher.match(TEST_WEATHER_WITH_LOCATION_AND_DATE_DIR), WeatherProvider.WEATHER_WITH_LOCATION_AND_DATE);        assertEquals("Error: The LOCATION URI was matched incorrectly.",                testMatcher.match(TEST_LOCATION_DIR), WeatherProvider.LOCATION);    }

···

4.10 register content provider1/2

這裡僅僅使能(開啟注釋) testProviderRegistry

public class TestProvider extends AndroidTestCase {    ...    /*        This test checks to make sure that the content provider is registered correctly.        Students: Uncomment this test to make sure you‘ve correctly registered the WeatherProvider.     */    public void testProviderRegistry() {        PackageManager pm = mContext.getPackageManager();        // We define the component name based on the package name from the context and the        // WeatherProvider class.        ComponentName componentName = new ComponentName(mContext.getPackageName(),                WeatherProvider.class.getName());        try {            // Fetch the provider info using the component name from the PackageManager            // This throws an exception if the provider isn‘t registered.            ProviderInfo providerInfo = pm.getProviderInfo(componentName, 0);            // Make sure that the registered authority matches the authority from the Contract.            assertEquals("Error: WeatherProvider registered with authority: " + providerInfo.authority +                    " instead of authority: " + WeatherContract.CONTENT_AUTHORITY,                    providerInfo.authority, WeatherContract.CONTENT_AUTHORITY);        } catch (PackageManager.NameNotFoundException e) {            // I guess the provider isn‘t registered correctly.            assertTrue("Error: WeatherProvider not registered at " + mContext.getPackageName(),                    false);        }    }    }
androidManifest update
        <provider            android:authorities="com.example.android.sunshine.app"            android:name=".data.WeatherProvider" />
小憩

增加provider布湊
- 估計要從 1代版本代碼 和 2代代碼 進行比較

聰明的編譯器

智能提示
android 在debug模式下,有很有趣的話題在裡面,比如變數值的提示
還有搜尋字元時,主動過濾注釋裡面字元

test ok 單元測試的方法 && testPractise


並且 我沒有選右鍵觸發,而是直接 run ( shift f10)
(4a-28 )裡面單元測試的方法,完全可以複現


- 展現啟動並執行配置
- 展示出錯情形如何定位錯誤
- 展示正常情況

使用的是 sunshine version2 的4.02的代碼,code: testPractise
todo 實踐後思考空白的android test工程是怎樣的?4.02章節裡面,命名只有有效3個testcase,怎麼顯示有6個testcase ?
testDb之testCreateDb

4.04 (git version) delete the testPractise,

實際運行記錄:我在所有的 assertTrue,assertFalse,assertEqual位置都下了斷點,但是只有testDb中的testCreateDb 被觸發,數字上,run視窗顯示的“6 of 6”ok,但6個中的4個被觸發,我懷疑這個6是不是顯示過時
testdb之testLocationTable

測試完全通過.

  • 該函數完整的調用了db的操作函數
    • insert
    • query

並且有趣的是調用了TestUtilities.validateCurrentRecord。
(這裡面還有2個assert,這裡面的斷言終於被觸發了)

這是我觀察中
testUtilities類中函數的第一次調用,
上一輪,我在這個類的static函數裡面設定斷點,
都沒有被調用。

還有這個類testUtilities提供了資料庫插入的樣本資料

todo實踐後思考:既然單元測試都是利用AndroidTestCase那麼為什麼每次都是testDb被調用,而其他AndroidTestCase的繼承類testUtilities 沒有被直接調用.
testWeatherTable 和重構 testLocationTable

4.06 lesson,
而且有趣的是前者內部調用調用了
locationTable的內容

竟然所有的測試通過了

todo 內容深入分析        // Fifth Step: Validate the location Query        TestUtilities.validateCurrentRecord("testInsertReadDb weatherEntry failed to validate",                weatherCursor, weatherValues);
小憩

github 前6個小節,就是認識單元測試

單元測試的魔力很大啊,這裡

後續

from 4.06 -4.10 (github)
測試函數有:
- test weatherContract
- test uri matcher
- test Provider
- test providerRegistery

構造一個content provider,每個模組都不能馬虎

晚安 小憩

至少方向是光明的

下一天 複習

解釋 前面 為什麼 不是 全部的uri都被命中

再看 weather provider 和 testProvider的示範
作者是逐一功能的enable,逐一測試。逐漸深入

幾乎每種testProvider的函數(query/getType/insert/updat)
都含有uri matcher的篩選

新近發現 可以 查看 每一個測試的內容:

video 4b-24 是個階段總結

bulkinsert 其實利用了事務,只有endtrancsation 才執行操作

小節

小節:整章節 就是 uri 使用
- define uri
- update uri(feflect to number)
- uri matcher (I think ,here addmatch)
- implement (I think, sUriMatcher.match(uri);)

說到,開源很多 封裝了 content provider ? toco
如何理解 notification oserver ..here

整合

至此,我們的content provider 還沒有和 database 聯合起來。
操作不是 test*.java,也不主要是 weatherprovider裡面

我們將精力集中到 FetchweatherTask
- addlocation
- getWeatherDataFromJson insert + query part
(網路收報後的處理常式)

看到凡是使用了getContentResolver的地方,都是利用了contentprovider的地方,

最後

為了ui theread 更加流暢,引出Loader
至此,我們的video 來到4b的借書,代碼
代碼範圍是:

todo 附code小節

android 你好
android 再見
呵呵,本部落格android暫停更新,如果有興趣可以簡訊聯絡

udacity android 實踐筆記: lesson 4 part b

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.