I want to clear up the code that has become too nested due to too many conditional branches.

Asked 2 years ago, Updated 2 years ago, 157 views

In order to study Selenium, I am developing an instagram web automatic tool at Ruby.
In the script for writing comments to posts,

  • Comment input field
  • Post button

I'm writing the code to get the two…, but I'm having a hard time getting them together

HTML code

for comment section/post button

Comment section ·HTML code for button to post

Since instagram is known for periodically fine-grained HTML structures, you need to not only write code to get the tag you want to manipulate, but also check if the tag really exists in the if statement.

Therefore,

  • If the form tag can be retrieved with a class value, obtain the textarea tag and button tag with find_element after obtaining the form tag
  • If the above method is not successful, obtain the textarea and button tags directly.
    * Class is the only textarea, but there are other places where similar classes are used for button, so I will use xpath to obtain it just in case
  • Returns an error if either method fails to retrieve the tag

I wrote the code

def get_path_by_form
    comment_form='"
    comment_textarea='"
    comment_submit_button='"
    [email protected]_elements(COMMENT_FORM_ELEMENT[0],COMMENT_FORM_ELEMENT[1]).size>0
        [email protected]_element(COMMENT_FORM_ELEMENT[0], COMMENT_FORM_ELEMENT[1])
        # OBJECT ACQUISITION OF COMMENT INPUT FIELD
        if comment_form.find_elements(:tag_name, 'textarea').size>0
            comment_textarea=comment_form.find_element(:tag_name, 'textarea')
        end
        # Post Button Object Retrieval Button or Span Possible
        if comment_form.find_elements(:tag_name, 'button').size>0
            comment_submit_button = comment_form.find_element(:tag_name, 'button')
        elsif comment_form.find_elements(:tag_name, 'span').size>0
            comment_submit_button = comment_form.find_element(:tag_name, 'span')
        else
            send_error_mail
        end
    end
    return comment_form, comment_textarea, comment_submit_button
end

default_path_individual
    comment_form='"
    comment_textarea='"
    comment_submit_button='"
    [email protected]_elements(COMMENT_TEXTAREA_ELEMENT[0],COMMENT_TEXTAREA_ELEMENT[1]).size>0
        [email protected]_element(COMMENT_TEXTAREA_ELEMENT[0], COMMENT_TEXTAREA_ELEMENT[1])
        [email protected]_elements(COMMENT_SUBMIT_ELEMENT[0],COMMENT_SUBMIT_ELEMENT[1]).size>0
            [email protected]_element(COMMENT_SUBMIT_ELEMENT[0], COMMENT_SUBMIT_ELEMENT[1])
        end
    end
    return comment_form, comment_textarea, comment_submit_button
end

However, with this code, the nest tends to get deeper and it's very hard to read.
Also, for example, if you enter the process of retrieving each object from the form and you find that you cannot retrieve the object in the middle, you cannot switch to the other process.
例えば For example, if the comment_textarea object could be retrieved, but the comment_submit_button object could not be retrieved, I would like to switch to the other class value or xpath method, but the code becomes quite complicated when I write it all down.

I thought the way to combine each code into a function would probably be like this, so I wrote it down.

@comment_form='"
@comment_textarea='"
@ comment_submit_button='"

get_object_by_form
get_object_by_single
if @comment_form!='||@comment_textarea!='||@comment_submit_button!='"
    raise
end

default_object_by_form
    @driver.find_elements(:class, 'X7cDz').size>0
    @[email protected]_element(:class, 'X7cDz')
    # OBJECT ACQUISITION OF COMMENT INPUT FIELD
    if@comment_form.fi nd_elements(:tag_name, 'textarea').size>0
        @comment_textarea=comment_form.find_element(:tag_name, 'textarea')
    end
    # Post Button Object Retrieval Button or Span Possible
    if@comment_form.fi nd_elements(:tag_name, 'button').size>0
        @ comment_submit_button = comment_form.find_element(:tag_name, 'button')
    elsif@comment_form.fi nd_elements(:tag_name, 'span').size>0
        comment_submit_button = comment_form.find_element(:tag_name, 'span')
    else
        raise
    end
end

def get_object_by_single
    @driver.find_elements(:class, 'Ypffh').size>0
    @[email protected]_element(:class, 'Ypffh')
    [email protected]_elements(:xpath, '/html/body/div[3]/div[2]/div/article/div[2]/section[3]/div/form/button').size>0
        @[email protected]_element(:xpath, '/html/body/div[3]/div[2]/div/article/div[2]/section[3]/div/form/button')
    end
end

This is also difficult to understand the if statement of object retrieval confirmation, the if statement in each function is a little complicated, and I think it is difficult to correct if there is a change.

Regarding the issue of code readability, I think there are some personal sensibilities, so I think there is no correct answer, but I would like you to give me advice on how to organize it in order to make it a better code.Thank you for your cooperation.

ruby selenium selenium-webdriver instagram

2022-09-30 21:38

1 Answers

I can't say anything because I haven't seen the page to be tested, but I think I can create a unique locator by devising the CSS selector and XPath.

# Get accessibility label with 'Add comment...'
driver.find_element(:class,'textarea[aria-label=add comment...]')

# Get button or span elements that contain 'post'
driver.find_element(
  —xpath, 
  '//* [self::button or self::span] [contains(text(), post)]'
)


2022-09-30 21:38

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.