2012-07-25 19 views
10

मैं पृष्ठ वस्तु पैटर्न सेलेनियम ने सुझाव दिया अनुसरण कर रहा हूँ, लेकिन मैं कैसे एक पृष्ठ के लिए एक और अधिक विशिष्ट WebElement पैदा करेगा। विशेष रूप से, हमारे पास हमारे पृष्ठों पर टेबल हैं और मैंने टेबल की विशिष्ट पंक्तियां प्राप्त करने के लिए कुछ सहायक कार्यों को लिखा है, एक तालिका की सामग्री वापस कर सकते हैं,सेलेनियम वेबड्राइवर वेबलेमेंट बढ़ाएं?

वर्तमान में, यहां एक पृष्ठ वस्तु का एक स्निपेट है जिसे मैंने बनाया है एक मेज:

public class PermissionsPage { 

    @FindBy(id = "studyPermissionsTable") 
    private WebElement permissionTable; 

    @FindBy(id = "studyPermissionAddPermission") 
    private WebElement addPermissionButton; 

    ... 

} 

तो, मुझे क्या करना चाहते हैं कि permissionsTable अधिक अनुकूलित WebElement उन तरीकों कि मैंने पहले बताया के कुछ है कि होना चाहिए।

उदाहरण के लिए:

public class TableWebElement extends WebElement { 
    WebElement table; 
    // a WebDriver needs to come into play here too I think 

    public List<Map<String, String>> getTableData() { 
     // code to do this 
    } 

    public int getTableSize() { 
     // code to do this 
    } 

    public WebElement getElementFromTable(String id) { 
     // code to do this 
    } 
} 

मुझे आशा है कि इस अर्थ है कि मैं क्या समझाने की कोशिश कर रहा हूँ बनाता है। मुझे लगता है कि मैं जो खोज रहा हूं वह इस कस्टम वेबलेमेंट को टेबल-विशिष्ट की कुछ अतिरिक्त सामग्री करने का एक तरीका है। एनोटेशन आधार पर पृष्ठ पर एक पृष्ठ को यह कस्टम तत्व जोड़ें और webelements रास्ता सेलेनियम तारों का लाभ उठाएं।

क्या यह संभव है? और यदि हां, तो क्या कोई जानता है कि यह कैसे किया जा सकता है?

उत्तर

20

मैं एक अंतरफलक है कि WebDriver इंटरफेस के सभी को जोड़ती है बनाया।

फिर एक कार्यान्वयन:

public class ElementImpl implements Element { 

    private final WebElement element; 

    public ElementImpl(final WebElement element) { 
     this.element = element; 
    } 

    @Override 
    public void click() { 
     element.click(); 
    } 

    @Override 
    public void sendKeys(CharSequence... keysToSend) { 
     element.sendKeys(keysToSend); 
    } 

    // And so on, delegates all the way down... 

} 

तो, उदाहरण के लिए एक चेक बॉक्स:

public class CheckBox extends ElementImpl { 

    public CheckBox(WebElement element) { 
     super(element); 
    } 

    public void toggle() { 
     getWrappedElement().click(); 
    } 

    public void check() { 
     if (!isChecked()) { 
      toggle(); 
     } 
    } 

    public void uncheck() { 
     if (isChecked()) { 
      toggle(); 
     } 
    } 

    public boolean isChecked() { 
     return getWrappedElement().isSelected(); 
    } 
} 

जब मेरी स्क्रिप्ट में इसका उपयोग करने:

CheckBox cb = new CheckBox(element); 
cb.uncheck(); 

मैं भी आए हैं Element कक्षाओं को लपेटने के तरीके के साथ। अंतर्निहित PageFactory को प्रतिस्थापित करने के लिए आपको कुछ कारखानों को बनाना होगा, लेकिन यह करने योग्य है, और यह बहुत लचीलापन देता है।

मैं अपनी साइट पर इस प्रक्रिया पर प्रलेखित है:

मैं भी एक परियोजना कहा जाता selophane कि इस और अन्य सवालों से प्रेरित था मिल गया है: selophane

+0

इस तरह मैंने इसे भी किया, लेकिन थोड़ा अलग .. मैंने एक अमूर्त वर्ग बनाया जो वेब इंटरफेस इंटरफेस को विस्तारित एक कस्टम इंटरफ़ेस लागू करता है। अंतिम कक्षा में अमूर्त और अतिरिक्त तरीकों में सभी विधियों को लोड किया गया। और मेरे आमंत्रण हैंडलर में, मैंने विधि को रोक दिया और इसे कमजोर वस्तु के तरीकों पर पुनर्निर्देशित किया यदि उन्हें कमजोर पड़ने वाले इंटरफ़ेस में घोषित किया गया हो; अन्यथा, मैंने तत्व को कस्टम वेबलेमेंट रैपर के साथ लपेट लिया; और विधि का आह्वान किया। पुनश्च। ब्लॉग के लिए +1 :) धन्यवाद! – rrw

0

क्यों WebElement विस्तार परेशान? क्या आप वास्तव में सेलेनियम पैकेज विकसित करने की कोशिश कर रहे हैं? फिर यदि आप हैं तो उस विधि को विस्तारित करने का अर्थ नहीं होगा जब तक कि आपके अतिरिक्त उपयोग आपके द्वारा उपयोग किए जाने वाले प्रत्येक वेब तत्व पर लागू नहीं हो सकते हैं, न कि केवल आपकी तालिका के लिए विशिष्ट

ऐसा क्यों न करें:

public class PermissionsPage extends TableWebElement{ 

...permissions stuff... 

} 

import WebElement 

public class TableWebElement{ 

...custom web elements pertaining to my page... 

} 

कि यदि आपके सवाल का जवाब मैं नहीं जानता, लेकिन यह मुझे लग रहा था इसे और अधिक एक वर्ग वास्तुकला सवाल कुछ और की तुलना में अधिक था।

0

मैं पैदा करेगा कि मैं क्या एक "SubPageObject" जो एक PageObject पर एक PageObject का प्रतिनिधित्व करता है फोन ...

लाभ यह है कि आप इसके लिए कस्टम मेड तरीकों बना सकते हैं और आप केवल WebElements तुम सच में भीतर की जरूरत को प्रारंभ कर सकते हैं यह सबपेज ऑब्जेक्ट।

1

साइड नोट:

public class TableWebElement implements WebElement { 

लेकिन उस मामले में आप सभी तरीकों में हैं को लागू करना चाहिए: WebElement वर्ग नहीं है, इसके इंटरफ़ेस अपने वर्ग यह कुछ ऐसा दिखाई होगा जिसका मतलब है WebDriver। और इसकी थोड़ी अधिक मात्रा में।

यहाँ जिस तरह से मैं यह कैसे करना है - के रूप में सेलेनियम द्वारा प्रस्तावित और मेरी अपनी कक्षाओं होने से "पहिया में नयापन लाया गया" मैं प्रस्तावित PageObjects की पूरी तरह से छुटकारा पा लिया। मैं पूरी आवेदन के लिए एक वर्ग है:

public class WebUI{ 
    private WebDriver driver;  
    private WebElement permissionTable; 

    public WebUI(){ 
     driver = new firefoxDriver(); 
    } 

    public WebDriver getDriver(){ 
    return driver; 
    } 

    public WebElement getPermissionTable(){ 
    return permissionTable; 
    } 

    public TableWebElement getTable(){ 
    permissionTable = driver.findElement(By.id("studyPermissionsTable")); 
    return new TableWebElement(this); 
    } 
} 

और फिर मैं अपने सहायक वर्गों परीक्षण के

public class TableWebElement{ 
    private WebUI webUI; 

public TableWebElement(WebUI wUI){ 
    this.webUI = wUI; 
} 

public int getTableSize() { 
    // because I dont know exactly what are you trying to achieve just few hints 
    // this is how you get to the WebDriver: 
    WebElement element = webUI.getDriver().findElement(By.id("foo")); 

    //this is how you get to already found table: 
    WebElement myTable = webUI.getPermissionTable(); 

} 

} 

नमूना है:

@Test 
public void testTableSize(){ 
    WebUI web = new WebUI(); 
    TableWebElement myTable = web.getTable(); 
    Assert.assertEquals(myTable.getSize(), 25); 
} 
+0

मैं इस विचार पसंद है, मैं "इसे आज़माने और आप जानते हैं कि यह कैसे जाता है सूचित करेंगे। – pipplupp

+0

बीटीडब्ल्यू, मैं नहीं जानता कि किसने नोट किया कि यह उत्तर उपयोगी नहीं है। मैं उत्सुक हूं कि किसी ने इस तरह क्यों मतदान किया। – pipplupp

+0

कम से कम आपको विचार पसंद है :) –

0

क्यों एक वेब तत्व आवरण नहीं? इस तरह?

class WEBElment 
{ 

public IWebElement Element; 

public WEBElement(/*send whatever you decide, a webelement, a by element, a locator whatever*/) 

{ 

Element = /*make the element from what you sent your self*/ 

} 


public bool IsDisplayed() 

{ 

return Element.Displayed; 

} 

} // end of class here 

लेकिन आप अपनी कक्षा को इससे अधिक जटिल बना सकते हैं। बस एक अवधारणा

1

इस के अनुवर्ती के रूप में, मैं यही कर रहा हूं (अगर किसी और के पास यह समस्या है)।

public class CustomTable { 

private WebDriver driver; 
private WebElement tableWebElement; 

public CustomTable(WebElement table, WebDriver driver) { 
    this.driver = driver; 
    tableWebElement = table; 
} 

public WebElement getTableWebElement() { 
    return tableWebElement; 
} 

public List<WebElement> getTableRows() { 
    String id = tableWebElement.getAttribute("id"); 
    return driver.findElements(By.xpath("//*[@id='" + id + "']/tbody/tr")); 
} 

public List<WebElement> getTableHeader() { 
    String id = tableWebElement.getAttribute("id"); 
    return tableWebElement.findElements(By.xpath("//*[@id='" + id + "']/thead/tr/th")); 
} 
.... more utility functions here 
} 

और फिर मैं किसी भी पन्ने में इस उपयोग करती हैं इसलिए जैसे कि यह हवाला कि बनाने के लिए:: नीचे वर्ग मैं एक WebElement करने के लिए एक आवरण के रूप में बनाया का एक टुकड़ा है

public class TestPage { 

@FindBy(id = "testTable") 
private WebElement myTestTable; 

/** 
* @return the myTestTable 
*/ 
public CustomTable getBrowserTable() { 
    return new CustomTable(myTestTable, getDriver()); 
} 

केवल बात यह है कि मुझे यह पसंद नहीं है कि जब पृष्ठ तालिका प्राप्त करना चाहता है, तो यह एक "नई" तालिका बनाता है। मैंने StaleReferenceExeptions से बचने के लिए ऐसा किया जो तब होता है जब तालिका में डेटा अपडेट किया जाता है (यानी सेल अपडेट किया गया, पंक्ति जोड़ा गया, पंक्ति हटा दी गई)। अगर किसी के पास कोई सुझाव है कि मैं हर बार एक नया उदाहरण बनाने से कैसे बच सकता हूं, लेकिन इसके बजाय अद्यतन वेबलेमेंट लौटाता है जो बहुत अच्छा होगा!

public interface Element extends WebElement, WrapsElement, Locatable {} 

यह चीजें WebElements जब एक तत्व लपेटकर कर सकते हैं के सभी लपेट के लिए बस नहीं है:

2

आप WebDriver Extensions ढांचे का उपयोग कर कस्टम वेबइलेमेंट्स बना सकते हैं जो हम प्रदान करते हैं bComponent वर्ग जो WebElement इंटरफ़ेस

अपने कस्टम WebElement

public class Table extends WebComponent { 
    @FindBy(tagName = "tr") 
    List<Row> rows; 

    public Row getRow(int row) { 
     return rows.get(row - 1); 
    } 

    public int getTableSize() { 
     return rows.size(); 
    } 

    public static class Row extends WebComponent { 
     @FindBy(tagName = "td") 
     List<WebElement> columns; 

     public WebElement getCell(int column) { 
      return columns.get(column - 1); 
     } 
    } 
} 

WebDriverExtensionFieldDecorator बनाएं ... और फिर एक @FindBy एनोटेशन के साथ अपने PageObject में जोड़ने और प्रयोग को लागू करता है जब PageFactory.initElements विधि बुला

public class PermissionPage { 
    public PermissionPage(WebDriver driver) { 
     PageFactory.initElements(new WebDriverExtensionFieldDecorator(driver), this); 
    } 

    @FindBy(id = "studyPermissionsTable") 
    public Table permissionTable; 

    @FindBy(id = "studyPermissionAddPermission") 
    public WebElement addPermissionButton; 
} 

...और फिर अपने परीक्षण में उपयोग

public class PermissionPageTest { 
    @Test 
    public void exampleTest() { 
     WebDriver driver = new FirefoxDriver(); 
     PermissionPage permissionPage = new PermissionPage(driver); 

     driver.get("http://www.url-to-permission-page.com"); 
     assertEquals(25, permissionPage.permissionTable.getTableSize()); 
     assertEquals("READ", permissionPage.permissionTable.getRow(2).getCell(1).getText()); 
     assertEquals("WRITE", permissionPage.permissionTable.getRow(2).getCell(2).getText()); 
     assertEquals("EXECUTE", permissionPage.permissionTable.getRow(2).getCell(3).getText()); 
    } 
} 




या और भी बेहतर WebDriver Extensions PageObject कार्यान्वयन

public class PermissionPage extends WebPage { 
    @FindBy(id = "studyPermissionsTable") 
    public Table permissionTable; 

    @FindBy(id = "studyPermissionAddPermission") 
    public WebElement addPermissionButton; 

    @Override 
    public void open(Object... arguments) { 
     open("http://www.url-to-permission-page.com"); 
     assertIsOpen(); 
    } 

    @Override 
    public void assertIsOpen(Object... arguments) throws AssertionError { 
     assertIsDisabled(permissionTable); 
     assertIsDisabled(addPermissionButton); 
    } 
} 

और स्थिर साथ JUnitRunner का उपयोग दावा WebElements

import static com.github.webdriverextensions.Bot.*; 

@RunWith(WebDriverRunner.class) 
public class PermissionPageTest { 

    PermissionPage permissionPage; 

    @Test 
    @Firefox 
    public void exampleTest() { 
     open(permissionPage); 
     assertSizeEquals(25, permissionPage.permissionTable.rows); 
     assertTextEquals("READ", permissionPage.permissionTable.getRow(2).getCell(1)); 
     assertTextEquals("WRITE", permissionPage.permissionTable.getRow(2).getCell(2)); 
     assertTextEquals("EXECUTE", permissionPage.permissionTable.getRow(2).getCell(3)); 
    } 
} 
के लिए तरीके
+0

मैंने 2 साल पहले इस प्रश्न को पोस्ट किया था और मैं खुद को इसी परिदृश्य में फिर से देख रहा हूं। मैं भूल गया कि मैंने यह सवाल भी पूछा था। मैं विभिन्न उत्तरों को देख रहा था और आपके वेबdriverextensions भयानक लग रहा है! सेलेनियम पत्तियां खोले गए छेद भरना। मैं आपके दस्तावेज को पढ़ने जा रहा हूं और इसे जाने दूंगा। – pipplupp

0

लो लो htmlelements ढांचे पर ठीक है, ऐसा लगता है कि आपको वास्तव में क्या चाहिए। इसने सामान्य तत्वों को पूर्व-कार्यान्वित किया है, जैसे चेकबॉक्स, रेडियोबॉक्स, टेबल, फॉर्म इत्यादि, आप आसानी से अपना स्वयं का बना सकते हैं और स्पष्ट तत्व पेड़ संरचना बनाने वाले अन्य तत्वों में एक तत्व डाल सकते हैं।

0

चरण 1) एक आधार वर्ग Element कहा जाता है कि IWrapsElement इंटरफ़ेस फैली बनाएं

public class Element : IWrapsElement 
{ 
    public IWebElement WrappedElement { get; set; } 
    public Element(IWebElement element) 
    { 
     this.WrappedElement = element; 
    } 
} 

चरण 2) प्रत्येक कस्टम तत्व के लिए एक कक्षा बनाएं और Element वर्ग

public class Checkbox : Element 
{ 
    public Checkbox(IWebElement element) : base(element) { } 

    public void Check(bool expected) 
    { 
     if (this.IsChecked()!= expected) 
     { 
      this.WrappedElement.Click(); 
     } 
    } 

    public bool IsChecked() 
    { 
     return this.WrappedElement.GetAttribute("checked") == "true"; 
    } 
} 

प्रयोग से विरासत:

ए)

Checkbox x = new Checkbox(driver.FindElement(By.Id("xyz"))); 
x.Check(true) 

ख)

private IWebElement _chkMale{ get; set; } 
[FindsBy(How = How.Name, Using = "chkMale")] 

private Checkbox ChkMale 
    { 
     get { return new Checkbox (_chkMale); } 
    } 
ChkMale.Check(true); 
संबंधित मुद्दे