質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.05%

Friendlyを使用したフォームアプリのテスト実施後の画面キャプチャ取得方法

解決済

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 2,425

score 59

<前提>
C#で生成しているフォームアプリの結合テストを、Codeer.Friendlyを用いた自動化テストによる実施を考えています。
Codder.Friendlyは、テスト対象のフォームアプリとは別のプロジェクトの単体テストプロジェクトで使用しています。
実際に各テストケースの動作自体はできました。

<問題>
この結合テストは、テストケース実施後、フォームアプリのキャプチャをエビデンスとして残したいです。
しかし、スクリーン全体であれば取得も可能なのですが、フォームアプリのみの画像に絞ろうとすると方法が分かりません。
フォームサイズなどは、WindowControlクラスから取得できるようなのですが、位置情報の取得に難航という状況です。
ProcessクラスやWindowsAppFriendクラスなどから取得できないかなども調査していますが、こちらも遅々として進まずといった具合です。
Codeer.Friendlyを用いたウィンドウキャプチャ取得方法はないでしょうか?

例)

// 実行ボタンクリックを経由して、テキストボックスの値をラベルに表示する動作のフォームアプリ対象
namespace FriendlyTest
{
    [TestClass]
    public class FriendlyTest
    {
        Process process;
        WindowsAppFrinend App;
        WindowControl Form;
        FormsButton ExeButton;
        FormsTextBox MessageTextBox;
        FormsLabel MessageLabel;

        [TestInitialize]
        public void TestInitialize()
        {
            process = Process.Start("Sample.exe");
            App = new WindowsAppFriend(process);
            WindowControl = new WindowControl(App.Type<Application>().OpenForms[0]);
            ExeButton = new FormsButton(Form.Dynamic().ExeButton);
            MessageTextBox = new FormsTextBox(Form.Dynamic().MessageTextBox);
            MessageLabel = new FormsLabel(Form.Dynamic().MessageLabel);
        }

        [TestCleanup]
        public void TestCleanup()
        {
            Process.GetProcessById(App.ProcessId).CloseMainWindow();
        }

        private void SaveCapture(string filePath)
        {
            Bitmap bmp = new Bitmap(Form.Size.Width, Form.Size.Height, PixelFormat.Format32bppArgb);
            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.CopyFromScreen(X位置, Y位置, 0, 0, Form.Size, CopyPixelOperation.SourceCopy);
                // ↑この処理の第1引数、第2引数の値に難航しています。
            }
            bmp.Save(filePath, ImageFormat.Png);
        }

        [TestMethod]
        public void テストケース001()
        {
            string inputMessage = "メッセージ";

            MessageTextBox.EmulateChangeText(inputMessage);
            ExeButton.EmulateClick();

            Assert.AreEqual(inputMessage, MessageLabel.Text);

            SaveCapture(MethodBase.GetCurrentMethod().Name + ".Png");
        }
    }
}

<補足>
開発言語:C#
開発環境:VisualStudio2015 Professional
.NET:バージョン4.6

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

作者です。Friendlyのエゴサで見つけました。
こんな感じでいかがでしょうか?

var form = new WindowControl(App.Type<Application>().OpenForms[0]);

//左上
Point pos = form.Dynamic().Location;
Size size = form.Dynamic().Size;
Bitmap bmp = new Bitmap(size.Width, size.Height, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
    g.CopyFromScreen(pos.X, pos.X, 0, 0, size, CopyPixelOperation.SourceCopy);
    Clipboard.SetDataObject(bmp, true);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/28 00:06

    ご回答ありがとうございます。
    作者様から回答が来るとは思いませんでした。
    感謝極まりという感じです。

    WindowControlクラス直下の情報しか見れていませんでした。
    Dynamic関数にLocationプロパティがあるのは盲点でした・・・。
    作業は自社PCになってくるので、確認は明日となってしまいますが、明日朝一で見てみます。

    キャンセル

0

いえいえー。
ちなみにDynamic関数はdynamic型を戻します。
それにプロパティがあるというより、Formクラスのプロパティを対象プロセスで実行して、その値を取得するという意味です。

//これで対象プロセスのオブジェクトへの参照を取得できる
//普通にFormのAPI(というかそれを継承したクラスのAPI)を全部使える
//ていうか、これもApplicationクラスのプロパティを対象プロセス内で実行している
dynamic form = App.Type<Application>().OpenForms[0];

//これはそれをラップしたもの
var wrap = new WindowControl(form);

//dynamicはラップを外してdyanmicに戻す
dynamic form2 = wrap.Dynamic();

//ややこしいんだけど、これは相手プロセス内のオブジェクトへの参照が取得できる
//オブジェクトはまだ相手プロセスの中にある
dynamic p = form.Location;

//実際の型に代入することで、コピーを取得できる
//この瞬間にコピーが対象プロセスから転送されてくる
Point pos = p;

//ちなみにAPIは全部使えます
//例えばBackColorとかも
//これもColorをシリアライズして対象プロセスへ転送して代入しています。
form.BackColor = Color.Red;


Friendlyの本質は別プロセスのAPIを外部から全部呼び出すというものです。
GitHubのドキュメントとか、私のブログとかを参照お願いします。
https://github.com/Codeer-Software/Friendly
ささいなことですが
疑問点あれば、また質問してくださいねー。
それから、Codeerではテスト自動化支援とか実装補助ツール販売とかやってますので、そちらのご利用も是非w

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/29 11:31

    詳細情報までありがとうございます。
    先の回答内容で実装してみた結果、求めていた通りのエビデンスファイルが作れました。
    これで進めていこうと思います。

    その他ツールにつきましては、自社の人と相談して検討ということでw

    キャンセル

  • 2019/03/29 22:34

    上手くいって良かったですね。
    >自社の人と相談して検討ということでw
    よろしくお願いしますw

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る