2017-08-30 16 views
15

Tôi có một yêu cầu như vậy:Java: gọi một phương thức với tên lưu trữ trong biến

String command = "click"; // this can have value such as clear, getLocation, getSize, getTagName etc. 
WebDriver driver = new ChromeDriver(options); //creating a webdriver object 
driver.findElement(By.id("id1")).click(); //Here I want "click" method should be called dynamically as per what I have stored in variable `command`. 

Vì vậy, là có cái gì có thể như:

driver.findElement(By.id("id1")).<something to call click()> 

Tôi đã nhìn Reflection trong Java , nhưng điều đó nhìn tôi phức tạp theo yêu cầu của tôi. Mọi con trỏ sẽ hữu ích!

Trả lời

10

cách đơn giản nhất để làm điều này là sử dụng phản ánh:.

String command = "click"; 
WebElement element = driver.findElement(By.id("id1")); 

Method method = WebElement.class.getMethod(command); 
method.invoke(element); 

Nếu bạn cũng muốn gọi By.id với phản ánh, sau đó bạn có thể làm điều này:

String command = "click"; 
String id = "id"; 

Method byMethod = By.class.getMethod(id, String.class); 
WebElement element = driver.findElement((By) byMethod.invoke(null, "id1")); 

Method method = WebElement.class.getMethod(command); 
method.invoke(element); 
+0

Tôi thực sự xin lỗi vì tôi đang hỏi một câu hỏi khác trong cùng một câu hỏi. Điều gì xảy ra nếu 'id' của tôi cũng được lưu trữ trong một biến. Ví dụ, một biến chứa 'id' hoặc' xpath' dựa trên đó tôi phải thực hiện hành động: 'driver.findElement (By. <Đến từ giá trị biến> (" id1 ")). ' Trong trường hợp này, giải pháp của bạn có thể được mở rộng ra sao? –

+0

@OmSao Tôi đã thay đổi mã một chút và thêm câu trả lời cho câu hỏi thứ hai của bạn. Vui lòng cho tôi biết nếu mã này hoạt động vì tôi chưa thử nghiệm. –

23

Biến của bạn thể hiện điều bạn muốn làm với phần tử web (trong trường hợp này, hãy nhấp vào phần tử đó).

Loại thích hợp cho điều đó không phải là String. Sử dụng một Consumer<WebElement> thay vì (hoặc bất kỳ loại gì driver.findElement() lợi nhuận là):

Consumer<WebElement> command = e -> e.click(); 

// ... 

command.accept(driver.findElement(By.id("id1"))); 

Đây là loại an toàn, hiệu quả, refactorable, và linh hoạt hơn nhiều so với phản xạ (kể từ khi người tiêu dùng của bạn có thể làm bất cứ điều gì nó muốn với yếu tố, không giới hạn trong một lời gọi phương thức duy nhất mà không bất kỳ tranh cãi Giống như ví dụ, nhập một số văn bản trong một lĩnh vực văn bản)

+4

điểm tốt, có thể có một 'Bản đồ ' để tìm nạp người tiêu dùng cần thiết bằng tên lệnh – Andrew

+0

Xin chào JB: Vì vậy, theo bạn, tôi phải đề cập đến 'nhấp chuột' trong khi phân bổ 'Người tiêu dùng '? Nếu tôi muốn gọi các lệnh như 'clear',' getLocation' vv, thì tôi phải xác định rõ ràng như là 'Consumer command = e -> e.clear(); ' Tôi có đúng hay không thiếu một cái gì đó? –

+1

Có. Cũng giống như bạn sẽ phải thay đổi 'String command =" click ";' thành 'String command =" clear ";'. Ngoại trừ bạn chắc chắn sẽ thực sự sử dụng một phương pháp tồn tại, IDE của bạn sẽ cung cấp tự động hoàn thành, bạn có thể chuyển đối số (tức là 'Consumer command = e -> e.sendKeys ("hello"); '). –

6

Về mặt thiết kế (và có lẽ điều này có thể được tối ưu hóa hơn nữa và trừu tượng cho chắc chắn), có lẽ bạn có thể xác định một Enum, chúng ta hãy đặt tên cho nó Action như:

public enum Action { 
CLICK, 
SENDKEY, 
etc 
} 

Trong mã của bạn sau đó làm:

Action action = <input>; 
// find the element 
WebElement element = driver.findElement(By.id("id1")); 
switch(action) { 
    case CLICK: 
     element.click(); 
     break; 
    case SENDKEY: 
     element.sendKey(); 
     break; 
    ... 
    default: 
     System.out.println("Undefined action"); 
     break; 
} 
0

có vẻ như bạn đang cố gắng xây dựng một khuôn khổ dựa trên từ khóa. Thành thật mà nói, tôi rất ngạc nhiên khi nghe bất kỳ câu chuyện thành công nào về điều đó. Đã luôn luôn tự hỏi mục đích thực sự của loại khung như vậy là gì? Ai sẽ dùng nó? Người quản lý, QA thủ công hoặc bên liên quan? Đối với tôi nó không có ý nghĩa liên quan đến những người không công nghệ trong các hoạt động tự động hóa thử nghiệm. Bất kỳ tự động hóa đòi hỏi kỹ năng công nghệ tốt (bao gồm lập trình và devops). Nếu không, xác suất thất bại là khá cao.

Dù sao, câu hỏi của bạn là nhiều hơn về stringsfunctional interfaces ánh xạ hoặc sử dụng phản chiếu rất thông minh. Nhưng vấn đề chính là bạn đã chọn sai [đầu vào] API cho điều đó. Dòng sau:

driver.findElement(locator).doSmth(); 

là cách đúng để không thành công, vì findElement sử dụng ngầm ẩn. Và tôi chắc chắn 100% rằng bạn sẽ bắt đầu tái cấu trúc toàn cầu/sửa đổi cách tiếp cận được triển khai, khi bạn phải đối mặt với NoSuchElementException/StaleElementReferenceException.

Cảm giác thông thường gợi ý sử dụng sự chờ đợi trôi chảy với ExpectedConditions. Nhưng nó sẽ làm cho công việc của bạn trở nên phức tạp hơn, bên cạnh những người định vị và hành động bạn phải suy nghĩ về các điều kiện cần được người dùng cung cấp.

Từ điểm kỹ thuật, tôi sẽ tạo trình bao bọc phổ biến trước tiên để đóng gói các cuộc gọi API WebDriver cấp thấp.Sẽ dễ dàng hơn nhiều khi lập bản đồ hoặc phản ánh các chức năng như vậy so với các cuộc gọi thô. Ví dụ. điều kiện dự kiến ​​có thể bị ẩn trên cấp độ enum:

@Getter 
@RequiredArgsConstructor 
public enum WaitCondition { 

    visible(ExpectedConditions::visibilityOfElementLocated), 
    enabled(ExpectedConditions::elementToBeClickable); 

    private final Function<By, ExpectedCondition<WebElement>> type; 
} 

Sẽ dễ dàng truy xuất hằng số bắt buộc bằng cách gọi điện, ví dụ: WaitCondition.valueOf("visible"), trong đó chuỗi đầu vào có thể được truyền từ bên ngoài.

wrapper API chung có thể trông giống như sau sau đó: ví dụ

protected void click(By locator) { 
    click(locator, enabled); 
} 

protected void click(By locator, WaitCondition condition) { 
    waitFor(locator, condition).click(); 
} 

private WebElement waitFor(By locator, WaitCondition condition) { 
    return wait.until(condition.getType().apply(locator)); 
} 

Mapping/phản ánh đã được cung cấp bởi những người khác trong chủ đề này. Chỉ cần lưu ý: nếu bạn thích sự phản chiếu, tôi khuyên bạn nên xem thư viện jOOR, đơn giản hóa quy trình này.

Các vấn đề liên quan