13

InternetExplorerのみのWebアプリケーションがあります。

テストを自動化するために何ができるかを模索しています。

Seleniumは優れたツールのように見えますが、リンクなどをアクティブ化できるようにするために、リンクがどこにあるかを伝える必要があります。アプリケーションはこの種のテストを念頭に置いて構築されていないため、通常id、主要な要素に属性はありません。

問題ありません。XPath式を使用できると思います。しかし、たとえばボタンの正しいXPathを見つけることは、ページのソースを調べることによって行われる場合、非常に苦痛です。

Firefox / Firebugでは、要素を選択し、「CopyXPath」を使用して式を取得できます。

IE Developerツールバーを持っていますが、イライラするほど近くにあります。クリックして関心のある要素を選択し、それに関するあらゆる種類の情報を表示できます。しかし、XPathを決定する便利な方法がわかりません。

では、IEでこれを行う方法はありますか?

4

3 に答える 3

7

ブックマークレットを使用します。XPathに関連するものが1つありますが、IEで機能するかどうかわかりません。私は行かなくてはなりませんが、それをテストして、IEで動作するかどうかを確認します。

私のブックマークからのWeb開発者向けの2つのブックマークレットサイト:SubsimpleのブックマークレットSquarefreeのブックマークレット。そこにはたくさんの便利なものがあります...

[編集]OK、戻ってきました。私が持っていたブックマークレットはFF専用で、最適ではありませんでした。元のアイデアを使って、ようやく書き直しました。見つけた場所が見つかりません。

拡張されたJS:

function getNode(node)
{
  var nodeExpr = node.tagName;
  if (nodeExpr == null)  // Eg. node = #text
    return null;
  if (node.id != '')
  {
    nodeExpr += "[@id='" + node.id + "']";
    // We don't really need to go back up to //HTML, since IDs are supposed
    // to be unique, so they are a good starting point.
    return "/" + nodeExpr;
  }
// We don't really need this
//~   if (node.className != '')
//~   {
//~     nodeExpr += "[@class='" + node.className + "']";
//~   }
  // Find rank of node among its type in the parent
  var rank = 1;
  var ps = node.previousSibling;
  while (ps != null)
  {
    if (ps.tagName == node.tagName)
    {
      rank++;
    }
    ps = ps.previousSibling;
  }
  if (rank > 1)
  {
    nodeExpr += '[' + rank + ']';
  }
  else
  {
    // First node of its kind at this level. Are there any others?
    var ns = node.nextSibling;
    while (ns != null)
    {
      if (ns.tagName == node.tagName)
      {
        // Yes, mark it as being the first one
        nodeExpr += '[1]';
        break;
      }
      ns = ns.nextSibling;
    }
  }
  return nodeExpr;
}

var currentNode;
// Standard (?)
if (window.getSelection != undefined) 
  currentNode = window.getSelection().anchorNode;
// IE (if no selection, that's BODY)
else 
  currentNode = document.selection.createRange().parentElement();
if (currentNode == null)
{
  alert("No selection");
  return;
}
var path = [];
// Walk up the Dom
while (currentNode != undefined)
{
  var pe = getNode(currentNode);
  if (pe != null)
  {
    path.push(pe);
    if (pe.indexOf('@id') != -1)
      break;  // Found an ID, no need to go upper, absolute path is OK
  }
  currentNode = currentNode.parentNode;
}
var xpath = "/" + path.reverse().join('/');
alert(xpath);
// Copy to clipboard
// IE
if (window.clipboardData) clipboardData.setData("Text", xpath);
// FF's code to handle clipboard is much more complex 
// and might need to change prefs to allow changing the clipboard content.
// I omit it here as it isn't part of the original request.

XPathを取得するには、要素を選択してブックマークレットをアクティブ化する必要があります。

さて、ブックマークレットのバージョン(ブックマークレットビルダーのおかげで):

IE
(IEは非常に長いブックマークレットが好きではないため、2つの部分に分割する必要がありました(最大サイズはIEのバージョンによって異なります)。最初のブックマークレット(function def)をアクティブにしてから、2番目のブックマークレットをアクティブにする必要があります。IE6でテスト済み。)

javascript:function getNode(node){var nodeExpr=node.tagName;if(!nodeExpr)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}
javascript:function o__o(){var currentNode=document.selection.createRange().parentElement();var path=[];while(currentNode){var pe=getNode(currentNode);if(pe){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');clipboardData.setData("Text", xpath);}o__o();

FF

javascript:function o__o(){function getNode(node){var nodeExpr=node.tagName;if(nodeExpr==null)return null;if(node.id!=''){nodeExpr+="[@id='"+node.id+"']";return "/"+nodeExpr;}var rank=1;var ps=node.previousSibling;while(ps!=null){if(ps.tagName==node.tagName){rank++;}ps=ps.previousSibling;}if(rank>1){nodeExpr+='['+rank+']';}else{var ns=node.nextSibling;while(ns!=null){if(ns.tagName==node.tagName){nodeExpr+='[1]';break;}ns=ns.nextSibling;}}return nodeExpr;}var currentNode=window.getSelection().anchorNode;if(currentNode==null){alert("No selection");return;}var path=[];while(currentNode!=undefined){var pe=getNode(currentNode);if(pe!=null){path.push(pe);if(pe.indexOf('@id')!=-1)break;}currentNode=currentNode.parentNode;}var xpath="/"+path.reverse().join('/');alert(xpath);}o__o();
于 2008-10-18T14:19:16.717 に答える
3

ブックマークレットの使い方に困惑していたポールなので、少し使い方を紹介したいと思います。混在を避けるために、別のメッセージで行います。

ブックマークレット (ファブレットとも呼ばれます) は、ブラウザのアドレス バーに (他の URL と同様に) 貼り付けて、現在のページで実行するように設計された小さな JavaScript スクリプト (原文ママ) です。
実行後 (貼り付けて Enter キーを押す)、ブックマークして再利用できます (IE のお気に入りに追加します)。ブラウザは代わりに元の URL をブックマークする可能性があることに注意してください。ブックマークを編集して、URL をスクリプトに置き換える必要があります。
もちろん、URL バーに追加してすばやくアクセスすることもできます。

これらのスクリプトは、現在のページの一部であるかのように動作し、グローバル JS 変数や関数、Dom オブジェクトなどにアクセスします。
これらは、非常に単純なもの (独創的なもの)javascript: alert("Hello world!");から、上記のような非常に複雑なものまであります。値が返された場合 (または最後の式に値がある場合)、現在のページがその値に置き換えられます。これを回避するには、alert(結果を表示するために) でスクリプトを終了するか、スクリプトを関数定義でラップして、上記のようにこの関数を呼び出すことができます。(最後に void(0); を付ける人もいますが、それは悪い習慣と見なされていることがわかりました。)

関数ソリューションには、スクリプトのすべての変数をアプレットに対してローカルにするという利点があり (varもちろん、で宣言されている場合)、ローカル ページ上のスクリプトとの干渉/副作用を回避します。これが、ラッピング関数にローカル スクリプトと衝突する可能性が低い名前を付ける必要がある理由でもあります。

一部のブラウザ (読み取り: "IE") では、ファブレットのサイズ (最大 . 長さはバージョンによって異なります (減少する傾向があります)。そのため、役に立たない空白をすべて削除し (上記のリンクの bookmarlet ビルダーはこれに適しています)、通常行っている null および undefined との明示的な比較を削除しました。また、favlet を 2 つに分割する必要がありました。最初の部分では関数を定義し (ページが変更/更新されない限り存続します)、2 番目の部分ではそれを使用します。

特に、ユーザー スクリプト (Greasemonkey 風) を許可していないブラウザーや、この拡張機能を使用しないブラウザーでは、便利なツールです。

于 2008-10-20T07:21:42.377 に答える
2

ブックマークレットのコードを C# に書き直したので、役に立つと思ったら使ってください ;-)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Anotation.Toolbar
{
    class XPath
    {
        public static string getXPath(mshtml.IHTMLElement element)
        {
            if (element == null)
                return "";
            mshtml.IHTMLElement currentNode = element;
            ArrayList path = new ArrayList();

            while (currentNode != null)
            {
                string pe = getNode(currentNode);
                if (pe != null)
                {
                    path.Add(pe);
                    if (pe.IndexOf("@id") != -1)
                        break;  // Found an ID, no need to go upper, absolute path is OK
                }
                currentNode = currentNode.parentElement;
            }
            path.Reverse();
            return join(path, "/");
        }

        private static string join(ArrayList items, string delimiter)
        {
          StringBuilder sb = new StringBuilder();
          foreach (object item in items)
          {
            if (item == null)
                continue;

            sb.Append(delimiter);
            sb.Append(item);
          }
          return sb.ToString();
        }

        private static string getNode(mshtml.IHTMLElement node)
        {
            string nodeExpr = node.tagName;
            if (nodeExpr == null)  // Eg. node = #text
                return null;
            if (node.id != "" && node.id != null)
            {
                nodeExpr += "[@id='" + node.id + "']";
                // We don't really need to go back up to //HTML, since IDs are supposed
                // to be unique, so they are a good starting point.
                return "/" + nodeExpr;
            }

            // Find rank of node among its type in the parent
            int rank = 1;
            mshtml.IHTMLDOMNode nodeDom = node as mshtml.IHTMLDOMNode;
            mshtml.IHTMLDOMNode psDom = nodeDom.previousSibling;
            mshtml.IHTMLElement ps = psDom as mshtml.IHTMLElement;
            while (ps != null)
            {
                if (ps.tagName == node.tagName)
                {
                    rank++;
                }
                psDom = psDom.previousSibling;
                ps = psDom as mshtml.IHTMLElement;
            }
            if (rank > 1)
            {
                nodeExpr += "[" + rank + "]";
            }
            else
            { // First node of its kind at this level. Are there any others?
                mshtml.IHTMLDOMNode nsDom = nodeDom.nextSibling;
                mshtml.IHTMLElement ns = nsDom as mshtml.IHTMLElement;
                while (ns != null)
                {
                    if (ns.tagName == node.tagName)
                    { // Yes, mark it as being the first one
                        nodeExpr += "[1]";
                        break;
                    }
                    nsDom = nsDom.nextSibling;
                    ns = nsDom as mshtml.IHTMLElement;
                }
            }
            return nodeExpr;
        }
    }
}
于 2011-03-27T20:04:50.710 に答える