ささいなことですが。

Windowsアプリテスト自動化ライブラリFriendly開発者の日記です。

VisualStudio for mac で Xamarinデビュー

初Xamarinやってみました!
しかも僕はAndroidiPhoneのプログラムも初です!

でも実はモバイルプログラム歴は3年くらいあるんですよ。
ガラケーですけどねw
ソフトバンク?なんですかそれ?僕がやってた頃はJ-PhoneとかVodafoneでしたよ。
あの頃は徹夜も散々やったなー(遠い目
まあ、昔話はこれくらいにして本編。

今回の目標

Androidの実機で動かすとこまでを目標にします。iOSもやりたいんですけど、僕まだiPhone持ってないんですよねー。

ソリューション新規作成

f:id:ishikawa-tatsuya:20161127214439p:plain:w300
まずは基本ということでNativeの方にします。 XamarinFormsはまた今度。Single View App を選択します。
f:id:ishikawa-tatsuya:20161127214544p:plain
プロジェクト名称はXamarinTestにしました。SharedCodeはPortable Class Libraryにしました。こちらはDLLとして処理を共有するものです。SharedLibraryはもっと原始的にソースコードを共有するプロジェクトです。
f:id:ishikawa-tatsuya:20161127214632p:plain
特に問題なくソリューションが作成されました。
f:id:ishikawa-tatsuya:20161127215259p:plain
プロジェクトは3つ作られています。
役割は以下のようです。直感的な構成ですね。

XamarinTest 共有コード
XamarinTest.Droid アンドロイド専用コード
XamarinTest.iOS iOS専用コード

F5

コードは全く触ってません。とりあえず、F5で実行してみます。
f:id:ishikawa-tatsuya:20161127220751p:plain:w300
おー、iOSエミュレータで起動しました。

Android

今度はAndroidでもやってみます。XamarinTest.Droidを右クリックしてスタートアッププロジェクトにします。
f:id:ishikawa-tatsuya:20161127221803p:plain:w300
でF5を押すと
f:id:ishikawa-tatsuya:20161127222001p:plain:w300

AndroidSDK更新

今日の記事ではコードは触ってませんが、生成されたコード見てると、Main.axmlを表示するときにエラーがでました。
f:id:ishikawa-tatsuya:20161127222359p:plain
アップデートしろって、こないだインストールしたばっかりやん・・・。やり方よくわからず手間取りましたが、素直にこの画面で「Open Android SDK」を選択すると SDK Manager が開いて更新できるようです。以下更新中です。
f:id:ishikawa-tatsuya:20161127222658p:plain

実機デバッグ

実機にインストールする一番簡単な方法がこれのようですね。どうやら実機でデバッグするとそのついでにデプロイされるらしいのでやってみます。

まずはAndroidデバッグモードにする

これは機種によるらしいですが、手元にあった HTC HTL 23 だと、以下の手順で画面遷移して、ビルド番号を7回タップで開発者モードにできました。
f:id:ishikawa-tatsuya:20161128072427p:plain
その後開発者向けオプションからUSBデバッグを有効にしました。ついでにデバッグ中にSleepになると不便なのでスリープを無効にしました。
f:id:ishikawa-tatsuya:20161128072714p:plain

接続

macの場合は特にドライバとか必要なく繋ぐだけでできるようになるとの噂です。では繋いでみましょう・・・。あかん!僕のmacにはUSBついてないやん!仕方ないので近所のエディオンに変換ケーブル買いに。
で、気を取り直して繋いでみました。最初どうするのかわからなかったですが、どうやら画面上部のバーのところで、実機が選択できるようになります。ここで繋いだ実機を選択します。
f:id:ishikawa-tatsuya:20161127223319p:plain
そして実行すると・・・
f:id:ishikawa-tatsuya:20161128072838p:plain:w300
で、デバッグを終了させてもアプリは残りました。一応目標達成かな。apkファイルの作り方とかはまた調べてみよっと。
f:id:ishikawa-tatsuya:20161128073138p:plain:w300

MFCのプロジェクト設定を変えてみる

なぜか今日はMFCですw
とある人から「MFC共Cのプロジェクトを<標準Windowsライブラリを使用する>に変更してもビルド通るんだけど」って話を聞きました。んー、まあもともと共有DLLをリンクしてるからありえなくもないよなーっと思って実験してみました。

MFCプロジェクトを新規作成
②プロジェクトの設定を<標準Windowsライブラリを使用する>に変更
f:id:ishikawa-tatsuya:20161123001432p:plain
そしてビルド!
f:id:ishikawa-tatsuya:20161123001459p:plain
えー、怒られたじゃん・・・。まあ、普通はそうだよねー。
とは言え、ビルドできたって言ってるんだから、やってみようじゃないですか。

_AFXDLLを定義

エラーで_AFXDLLが定義されてないよって言われてるから、無理やり定義します。
f:id:ishikawa-tatsuya:20161123001909p:plain
で、ビルドすると・・・
f:id:ishikawa-tatsuya:20161123002032p:plain
あー、そういうと思ったよ。でもめげないよー。

_tWinMainを作成

たしかappmodul.cppにそんなの定義されてたよねー。その関数だけコピってきます。
で、これをMainFrm.cppの最後に貼る。(場所はどこでもいいです。)

extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

さー、ビルド!おー、通ったよ。で実行すると・・・
f:id:ishikawa-tatsuya:20161123002639p:plain
動きましたー

結論

  • 普通にやるとビルド通らない
  • 無理やりやるとビルド通って実行もできる

追伸

MFCたちもWindowsの仲間に入れてやってください・・・
f:id:ishikawa-tatsuya:20161123005416p:plain

Visual Studio for Mac ⇔ Windows (WinFormsがMacでビルド、実行できたよ)

Visual Studio for Mac を触り始めましたが、Windows版との互換性が気になりました。ちょっと実験してみます。(ていうか、この辺はXamarinStudioと同じなんでしょうけど、XamarinStudioの仕様も知らないので)

コンソールアプリ

for Mac で作ったコンソールアプリをそのままWindowsの方にコピーしてみました。
で、Visual Studio 2015 で開いてみます。
おー、開けたよ!逆になんで?
f:id:ishikawa-tatsuya:20161120163921p:plain
プロジェクト情報を見てみると、.NET Framework 4.5 になっていました。
for Macの方でプロジェクト情報見ると・・・
Mac版ではプロジェクトのところからメニューを開いてオプションを選択するようです。
f:id:ishikawa-tatsuya:20161121063356p:plain:w300
で、全般を選択すると
f:id:ishikawa-tatsuya:20161121063650p:plain
なるほど、コンソールアプリはMono/.NetFramework4.5で作られるんですね。
では、macの方でビルドしたexeをWindowsで実行すると・・・。
f:id:ishikawa-tatsuya:20161121063130p:plain
普通に実行できました。
逆にこれはmacでは、普通には動かないんですね。
mac初心者なんで最初あれ?ってなったんですが、exeってmacの実行ファイルではないようです。macで動かすためにはホストする何かが必要になります。で、.Netアプリを実行するにはmonoランタイムを使います。ターミナルでexeのフォルダまで行って、monoコマンドを実行します。
f:id:ishikawa-tatsuya:20161121064059p:plain

WinForms

どうも調べて見るとMonoのランタイムでWinFormsもある程度動くようです。ちょっとやってみたいですね。でも Visual Studio for Mac の新規作成ではWinFormsなんてない。もはや関わりたくない感がすごいw。でも先ほどのConsoleアプリの実験で分かったようにWindows版とMac版でソリューションの互換性はあるようです。というわけでWindows版でソリューション作ってそれをコピーしてみます。.Netのバージョンは4.5にしておきます。で、開くと
f:id:ishikawa-tatsuya:20161121064352p:plain
おー、開けた!
そして実行もしてみます。
f:id:ishikawa-tatsuya:20161121064855p:plain:w280
実行もできますね。結構便利な気はしますが、もはや主流ではないんですねー。
それから、フォームのデザイナも開くことはできませんでした。残念。

Mac買いました!そしてVisual Studio for Macをインストールしましたー。

なんと、人生初のmacを買いました。
このブログもmacで書いてます。
慣れてないから、時間かかるw

そしてVisual Studio for Macをインストールしました。

www.visualstudio.com
インストール時もキャプチャしておけばよかったですね。
まあ、特に問題なく入りました。
(でも、前日にXCodeJDK、XamarinStudioを入れていたからかも。
起動してみるとこんな感じ。
f:id:ishikawa-tatsuya:20161117232631p:plain

実験

試しにConsoleアプリを作ってみました。Xamarin? 最初はシンプルに行きましょうw
f:id:ishikawa-tatsuya:20161117232927p:plain
あれ?マック用のアプリとかも作れるんですねー。とりあえず、今回はコンソールプロジェクトを選択しました。
f:id:ishikawa-tatsuya:20161117233154p:plain
で、作成を押すとプロジェクトができあがります。
さー、実行!F5。おーF5効いたよ。ショートカットキーがWindows版と同じなのが嬉しいですね。
f:id:ishikawa-tatsuya:20161117233639p:plain
あれー、でもプログラム終了しても、コンソールのこるんだ。ちょっとウザい。
ステップ実行試してみます。
f:id:ishikawa-tatsuya:20161117234437p:plain
F9でブレイクはってF5で実行。
そんで止まったら、F10でステップ!いいねー。
さー、では関数にステップイン、F11...
ノー!どういうことやねん!
f:id:ishikawa-tatsuya:20161117234843p:plain
F11はMacのシステム的なキーなんかな?デスクトップが表示されました。
おいおい、ステップインどうすんだよ!
あ、ここでキー設定みれるっぽい。
f:id:ishikawa-tatsuya:20161117235332p:plain
Macはアプリのメニューがデスクトップの上部にでるんですねー。慣れてないから違和感がすごいw
f:id:ishikawa-tatsuya:20161117235417p:plain
ステップで検索してみると、出てきました。なるほど、それぞれCommandキーをつければいいのね。
ステップインが Command+F11
ステップアウトが Command+Shift+F11
ついでに、定義位置にジャンプはF12で動作しました。

Nuget

今日のところはNuget見つけれたら満足ですね。ここにありました。
f:id:ishikawa-tatsuya:20161118000340p:plain
f:id:ishikawa-tatsuya:20161118000457p:plain
試しにJSON入れてみました。
f:id:ishikawa-tatsuya:20161118001825p:plain

いい感じです。

ぱっと使いそうな機能を試してみましたが、普通に使えて逆にびっくりですw
もっと使い込んでみようっと。

dotnetConf関西 2016 で登壇してきました。

これですね。
.Netの新しい機能の勉強会です。
connpass.com

僕はWPFとUWPのテスト自動化に関して話をしてきました。
まあ、WPFは新技術でもないですけど・・・。
とは言え、いい感じに枯れてきたので、日本でもようやく導入が始まってきたようですね。(過去何回も、日本でもようやく・・・的な話を聞きましたが、今回は本当のようですw)

WPFはFriendlyでバッチリテストできます。
UWPも結構いいところまで来てるんですよねー。
これも早いところAPI固めて正式版にしたい。

www.slideshare.net

デモが多かったのですが、
こちらから、そのアプリとテストをダウンロードできますので
よろしければ試してみてください。
github.com

Friendly.UWP_α 0.0.5 をリリースしました。

すごい久しぶりのリリースです。半年以上ほったらかしてましたからねー。
www.nuget.org

そもそも、動かなくなってた

おいおいって感じですが。UWPの画面描画に関するオブジェクトの生成をメインスレッド以外で実行した場合、例外が発生するようになっていました。Microsoftも結構な破壊的変更をぶっこんできますねー。newもメインスレッドで実行するようにしました。

UWPAppFriendから現在のウィンドウを取得できるプロパティを追加

地味機能です。さらにそこからContentも取得できます。もちろんFriendlyの素の機能でもできますが、インテリセンス効いた方が格段に便利ですよね。

var content = app.CurrentWindow.Content;

VisualTree検索機能

WPFの時に評判の良かったツリーからの検索機能を実装しました。UWPはLogicalTreeってないんですねー。VisualTreeからタイプとバインディングで検索できるようにしています。

var tree = app.CurrentWindow.Content.VisualTree();

//型から取得
var textBox = tree.ByType("Windows.UI.Xaml.Controls.TextBox").Single();

//バインディングパスから取得
var button = tree.ByBinding("Execute").Single());

コントロールラッパーの作成開始

とりあえず、以下作りました。順次増やしていきます。

  • Button
  • CheckBox
  • RadioButton
  • ComoboBox
  • ListBox
  • TextBox

で、今のところこんな操作ができます。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Codeer.Friendly.Dynamic;
using System.IO;
using VSHTC.Friendly.PinInterface;
using EnvDTE80;

namespace Friendly.UWP.Test
{
    [TestClass]
    public class TestAttach
    {
        [TestMethod]
        public void Test()
        {
            using (var app = new UWPAppFriend(new ByVisualStudio(Path.GetFullPath("../../../TargetApp/TargetApp.sln"))
            {
                VisualStudioPath = @"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe",
                ChangeVisualStudioSetting = (vs, dteSrc)=>
                {
                    var dte = dteSrc.Pin<DTE2>();
                    dte.Solution.SolutionBuild.SolutionConfigurations.Item(3).Activate();
                }
            }))
            {
                //Visual Tree取得
                var tree = app.CurrentWindow.Content.VisualTree();

                //テキストボックス
                var textBox = new TextBox(tree.ByType(TextBox.TypeFullName).Single());
                textBox.EmulateChangeText("abc");

                //ボタン
                var button = new Button(tree.ByBinding("Execute").Single());
                button.EmulateClick();

                //コンボボックス
                var comboBox = new ComboBox(tree.ByType(ComboBox.TypeFullName).Single());
                comboBox.EmulateChangeSelectedIndex(2);

                //リストボックス
                var listBox = new ListBox(tree.ByType(ListBox.TypeFullName).Single());
                listBox.EmulateChangeSelectedIndex(2);

                //ラジオボタン
                var radioButton = new RadioButton(tree.ByType(RadioButton.TypeFullName).Single());
                radioButton.EmulateCheck(true);

                //チェックボタン
                var check = new CheckBox(tree.ByType(CheckBox.TypeFullName).Single());
                check.EmulateCheck(true);

                //もちろん素のFriendlyの機能で、内部APIを直で実行できます。
                //背景色変更
                var mainPage = app.CurrentWindow.Content.Dynamic().Content;
                var color = app.Type("Windows.UI.Colors").Blue;
                var brush = app.Type("Windows.UI.Xaml.Media.SolidColorBrush")(color);
                mainPage.Content.Background = brush;
            }
        }
    }
}

実行結果です。
f:id:ishikawa-tatsuya:20160905010130p:plain

LambdicSqlがβ版になりました!

www.nuget.org

やっとβ版になりました。
1.0に向けて仕様は、ほぼ固まったかなー。これもおださんをはじめ、色々助言いただいた方々のおかげです。ありがとうございます!ちなみに織田さんには少し前からNugetのOwerにも入ってもらってます。

SQLをLambdaから作成するライブラリです

その名のとおりです。Linqとはアプローチが違って、書いたC#が(割と)そのままSQLになります。

public void TestStandard()
{
    var min = 3000;

    //C#でラムダを書くと
    var query = Db<DB>.Sql(db =>
        Select(new SelectData()
        {
            Name = db.tbl_staff.name,
            PaymentDate = db.tbl_remuneration.payment_date,
            Money = db.tbl_remuneration.money,
        }).
        From(db.tbl_remuneration).
            Join(db.tbl_staff, db.tbl_staff.id == db.tbl_remuneration.staff_id).
        Where(min < db.tbl_remuneration.money && db.tbl_remuneration.money < 4000));

    //文字列とパラメータになる!
    //デバッグ出力してみます。
    var info = query.Build(_connection.GetType());
    Debug.Print(info.SqlText);

    //後は、それを投げるだけ
    //Dapper使ってたらこんな感じです。
    var datas = _connection.Query(query).ToList();
}
SELECT
    tbl_staff.name AS Name,
    tbl_remuneration.payment_date AS PaymentDate,
    tbl_remuneration.money AS Money
FROM tbl_remuneration
    JOIN tbl_staff ON (tbl_staff.id) = (tbl_remuneration.staff_id)
WHERE ((@min) < (tbl_remuneration.money)) AND ((tbl_remuneration.money) < (@p_1))

シンプルなものだけじゃなくて、こんな複雑なものも書けます。

できること

こちらに一覧を書きました。(長いので転記はあきらめました。参照お願いします。)
github.com

多くの句、キーワード、関数、Window関数に対応

私が最近買った、SQLの入門書に書かれているDCLは全て対応しましたw。この本に載っているDCLはすべて書ける!(はず)CreateとかDropのようなDDLはサポートしていません。
「SQL ゼロからはじめるデータベース操作」
f:id:ishikawa-tatsuya:20160902233751p:plain

主要DBで動作

以下で動作確認しています。とは言え、同じ書き方でOKってわけでなくて、普通のSQLと同様に関数や句はDBごとに使える、使えないはあります。

DataBase type Support
SQL Server
SQLite
PostgreSQL
Oracle
MySQL
DB2

その他、便利機能が盛りだくさん

便利機能が盛りだくさんです。記事はα版の時に書いたものをβ版の仕様で修正していますので、参照お願いします。Dapper、EntityFrameworkの操作運用に関してはさらに便利にしたのでまた書きます。

早く1.0になりたい

残件は

  1. 関数コメント(英語)
  2. テスト追加
  3. チューニング
  4. リファクタリング

①が一番難易度高い...
9月中リリースを目標に進めよっと。