1

Windows 7 64 ビットの IE 9 で WatiN 2.1.0 (C#) を使用しています。

私の問題は、この関数を呼び出すことです

ie.FileUpload(Find.ByName(someRegExp)).Set(fileName);

は非常に遅いです。
つまり、オブジェクトがうまく見つかったということです。このコードはファイル ダイアログを開きますが、WatiN のタイムアウトよりもはるかに長い約 3 ~ 5 分後に、ファイル名の入力を開始します。この後、残りのテストは正常に機能しています。

これに対する治療法はありますか?この大きな遅延は非常に煩わしく、ファイルのアップロードを伴うテスト ケースが増えると、テスト期間が大幅に長くなります。

4

3 に答える 3

2

わかりました、これは言うまでもなく Watin のソリューションではありませんが、まったく同じ問題がありました。私たちのファイル ブラウザ テストは合計テスト時間の多くを占めていました。私はファイルのアップロードのために Watin を追い出し、代わりに (恐ろしい) UIAutomation フレームワークを使用することで解決しました。

使用例:

    public CustomFileUpload FileUpload
    {
        get
        {
            return new CustomFileUpload(WebBrowser.Current.hWnd, "_Layout");
            //return Document.FileUpload(Find.ByName("file"));
        }
    }

テスト プロジェクトで「UIAutomationClient」と「UIAutomationTypes」への参照を追加する必要があります。また、以下のソリューションは一般的なものではないため、ニーズに合わせて微調整する必要がある場合があります.

public class CustomFileUpload
{
    private readonly IntPtr _browserHandle;
    private readonly string _tabHeader;

    public CustomFileUpload(IntPtr browserHandle, string tabHeader)
    {
        _browserHandle = browserHandle;
        _tabHeader = tabHeader;
    }

    public void Set(string filePath)
    {
        Automate(filePath);
    }

    private void Automate(string filePath)
    {
        AutomationElement browser = AutomationElement.FromHandle(_browserHandle);

        AutomationElement tab = FindTab(browser, _tabHeader);


        // IE10 adds the name (or value?) "Browse..." to the upload-button. Need to hack it :)
        AutomationElement uploadButton = tab.FindFirst(TreeScope.Children,
                                                            new AndCondition(
                                                                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
                                                                new PropertyCondition(AutomationElement.NameProperty, "Browse..."))) ??
                                                                tab.FindFirst(TreeScope.Children,
                                                        new AndCondition(
                                                            new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button),
                                                            new PropertyCondition(AutomationElement.NameProperty, "")));

        ClickButton(uploadButton);

        var openFileDialog = WaitUntilOpenFileDialogAvailable();

        var valuePattern = FindFileNameTextBox(openFileDialog).GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;

        if (valuePattern == null)
            throw new InvalidOperationException("Can't set the file path");

        valuePattern.SetValue(filePath);

        SetFocusToSomethingElse(browser);

        var okButton = WaitUntilOkButtonLoaded(openFileDialog);

        ClickButton(okButton);
    }

    private static AutomationElement FindTab(AutomationElement browser, string tabHeader)
    {
        return browser.FindFirst(TreeScope.Descendants,
                                 new AndCondition(
                                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
                                     new PropertyCondition(AutomationElement.NameProperty, tabHeader)));
    }

    private static void SetFocusToSomethingElse(AutomationElement elementWhichShouldNotBeSelected)
    {
        do
        {
            foreach (AutomationElement element in AutomationElement.RootElement.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.IsKeyboardFocusableProperty, true)))
            {
                if (element != elementWhichShouldNotBeSelected)
                {
                    element.SetFocus();
                    return;
                }
            }

        } while (true);
    }

    private static AutomationElement WaitUntilOkButtonLoaded(AutomationElement openFileDialog)
    {
        AutomationElement okButton;

        do
        {
            okButton = openFileDialog.FindFirst(TreeScope.Children,
                                                new AndCondition(
                                                    new PropertyCondition(AutomationElement.IsContentElementProperty, true),
                                                    new PropertyCondition(AutomationElement.IsControlElementProperty, true),
                                                    new PropertyCondition(AutomationElement.NameProperty, "Open"),
                                                    new PropertyCondition(AutomationElement.IsInvokePatternAvailableProperty, true)
                                                    ));

        } while (okButton == null);

        return okButton;
    }

    private static AutomationElement WaitUntilOpenFileDialogAvailable()
    {
        AutomationElement openFileDialog = null;

        do
        {

            AutomationElement openFileDialogContainer = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "Alternate Modal Top Most"));

            if (openFileDialogContainer != null)
                openFileDialog = openFileDialogContainer.FindFirst(TreeScope.Children, Condition.TrueCondition);
        } while (openFileDialog == null);

        return openFileDialog;
    }

    private static void ClickButton(AutomationElement button)
    {            
        var clickPattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;

        if (clickPattern == null)
            throw new InvalidOperationException("Can't find the buttons click pattern");

        clickPattern.Invoke();
    }

    private static AutomationElement FindFileNameTextBox(AutomationElement openFileDialog)
    {
        AutomationElement findElementToTypePathInto;

        do
        {
            findElementToTypePathInto = openFileDialog.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.NameProperty, "File name:"), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
        } while (findElementToTypePathInto == null);

        return findElementToTypePathInto;
    }

}
于 2012-11-27T11:13:00.630 に答える
1

少し単純な解決策がありました(これも自動化に依存していますが、ファイルを選択するためだけです)。ファイル入力で .ClickNoWait() を使用しましたが、ブラウザーがハングすることはありませんでした。

次に、選択するファイルを設定する拡張メソッドを作成しました。

public static void UploadFile(this Browser browser, string uploadPath)
{
    var trw = new TreeWalker(Condition.TrueCondition);
    var mainWindowElement = trw.GetParent(AutomationElement.FromHandle(browser.hWnd));

    // Wait for the dialog to open
    Thread.Sleep(1000);

    // Get the select dialog
    var selectDialogElement = mainWindowElement.FindFirst(TreeScope.Descendants, 
        new PropertyCondition(AutomationElement.NameProperty, "Choose File to Upload"));

    // Get the file name box and set the path
    var selectTextElement = selectDialogElement.FindFirst(
        TreeScope.Descendants,
        new AndCondition(new PropertyCondition(AutomationElement.NameProperty, "File name:"),
            new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit)));
    var selectValue = (ValuePattern)selectTextElement.GetCurrentPattern(ValuePattern.Pattern);
    selectValue.SetValue(uploadPath);

    // Get the open button and click it
    var openButtonElement = selectDialogElement.FindFirst(TreeScope.Descendants,
        new AndCondition(new PropertyCondition(AutomationElement.NameProperty, "Open"),
            new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)));
    var openButtonClick = (InvokePattern)openButtonElement.GetCurrentPattern(InvokePattern.Pattern);
    openButtonClick.Invoke();
}

使用例:

var browser = (IE)Document.DomContainer;     
Document.FileUpload(Find.BySelector("#FileUpload")).ClickNoWait();
browser.UploadFile("c:\\myfile.txt");
Document.Button(Find.BySelector("#submit")).Click();

UIAutomation は UploadFile(filepath) の呼び出しから引き継ぎ、ダイアログ ウィンドウを見つけて、ユーザーが行ったかのようにフォームに入力します。

于 2014-02-03T11:46:19.337 に答える
0

また、WatiN がファイル アップロード ダイアログ ボックスでファイル名の入力を開始するまでに 3 ~ 5 分の遅延が発生しました。

これは、IE で開発者ツール ペインが開いているときに発生するようです。開いていないときは、すぐにタイピングを開始できます。

デフォルトのブラウザに関するプロンプトや同様のポップアップも、遅延の原因になっているようです。

于 2013-02-07T14:43:31.867 に答える