plx23
plx23

Reputation: 89

Web automation script efficiency

I wrote an extremely long code to automate some web browsing. It is made up of 51 blocks of code that consist of 50 lines of codes in each, as the picture illustrates. I need to run this script more than once, but every time I do run it all of those 51 blocks need a small tweak. As of now, I do the small tweak manually but there must be a way to condense my code and make it easier to run multiple times.

In each of those blocks, only 4 lines that are spread out within the block of code need change. Is there a way to 'wrap' the rest of the code in some function while giving myself an option to simply type in the 4 lines manually once at have it applied to all 51 blocks?

enter image description here

Here is an example of one of the red blocks (picture) of code:

driver = webdriver.Chrome()
driver.maximize_window()
driver.get("website")
driver.find_element_by_id("email").send_keys("[email protected]")
driver.find_element_by_id("password").send_keys("password123")
driver.find_element_by_id("submit").click()
driver.get("website2")
driver.implicitly_wait(30)
driver.find_element_by_id("ui-id-6").click()
day = driver.find_element_by_xpath("/html/body/main/div[2]/div[6]/div[3]/div[4]/div/div[2]/table/tbody/tr[1]/td[2]")
ActionChains(driver).move_to_element(day).click().perform()
WebDriverWait(driver, 60).until(EC.presence_of_element_located((By.XPATH,"/html/body/main/div[2]/div[6]/div[3]/div[4]/div/div[2]/table/tbody/tr/td/ul/li[2]/h3/a[3]")))
driver.execute_script("window.scrollBy(0,500)","")

driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[4]/div/div[2]/table/tbody/tr/td/ul/li[2]/h3/a[3]').click()

driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[2]/form/div[3]/ul[1]/li[3]/i').click()
driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[2]/form/div[3]/ul[1]/li[2]/i').click()
driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[2]/form/div[3]/ul[1]/li[1]/i').click()
driver.find_element_by_id('scheduleDate').click()
day = driver.find_element_by_xpath('/html/body/div[4]/table/tbody/tr[5]/td[2]/a')
ActionChains(driver).move_to_element(day).click().perform()
driver.implicitly_wait(30)
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
img = driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[2]/form/div[2]/div/div[3]/div[1]/button[2]')
ActionChains(driver).move_to_element(img).click().perform()
driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[4]/div/div[2]/div/ul/li/div[1]/img').click()
driver.execute_script('window.scrollTo(0, 500)')

driver.find_element_by_id("quickpostHashTag").send_keys("tags",(Keys.RETURN))

driver.find_element_by_id("calendarTitle").clear()

driver.find_element_by_id('calendarTitle').send_keys('title')

driver.find_element_by_id('calendarMessage').clear()

driver.find_element_by_id('calendarMessage').send_keys("msg")

driver.implicitly_wait(30)
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
driver.find_element_by_xpath('/html/body/main/div[2]/div[6]/div[3]/div[2]/form/div[4]/a').click()
driver.execute_script('window.scrollTo(0, document.body.scrollHeight)')
driver.find_element_by_xpath("/html/body/main/div[2]/div[6]/div[3]/div[2]/div/div[3]/div/button[1]").click()
driver.close()

The lines that change for every time I run this are - the one that is seperated by blank spaces from top and bottom and then the ones with 'tags', 'title' and 'msg'

Upvotes: 1

Views: 47

Answers (1)

Alexandru Sandu
Alexandru Sandu

Reputation: 143

It really depends on what those 4 lines are doing, honestly, and how they impact the rest of the logic.

Either way you can try and externalize those lines of code (either variable assignment or function calls, whichever they may be) with parameters, therefore try to figure out which parameters you need for those 4 lines, or if in themselves are used in the rest of code block, externalize the rest of it as a function accepting parameters corresponding to the 4 lines of code.

Once you are able to split the 4 lines from the rest of the code, create a structure similar to a list/dict/object whichever fits your case better in which to add that "4 lines of code" differing from each of the 50-51 blocks you have, and ultimately, iterate over said structure and call the already externalized from previous steps block of code, providing the 4-lines of content form said iteration.

TL;DR:

  • split the 4 lines from the rest of the block

  • rest of the block becomes standalone function (let's call it execute_process)

  • make the 4 lines either a function or parameters for the rest of block

  • create a structure (list/dict/obj) encompassing the possibilities for the 4-lines of code -> let's call it process_params

  • iterate over said structure and feed each of the process_param from the created process_params to the execute_process

    ** Now you have only 47 lines of code in a function, and a structure encompassing the 4 lines with each possible config for them.

Example: So you have an XPATH and 3 IDs that are changing? You could easily create a list of dictionaries for example in which you would hold the values for the lines that are changing, and add the rest of the code in a function, accepting those 4-5 parameters. After that, just iterate over said list of dictionaries and call the function using the available data.

for data_feed in test_scenarios:
    execute_test(xpath=data_feed["xpath"],
                 tags=data_feed["tags"],
                 title=data_feed["title"],
                 msg=data_feed["msg"])

Upvotes: 1

Related Questions