Selenium WebDriver adalah framework yang digunakan untuk otomatisasi pengujian aplikasi web. Ia bekerja dengan cara mengontrol browser secara langsung untuk menjalankan operasi seperti mengklik tombol, mengisi formulir, dan menavigasi halaman web. Dengan menggunakan selenium, maka memungkinkan pengujian aplikasi web dilakukan secara otomatis di berbagai peramban (seperti Chrome, Firefox, dan Edge). 

Karena sifatnya yang bisa menjalankan browser otomatis bahkan mengklik dan membuka halaman otomatis, maka selenium tidak hanya digunakan untuk pengujian aplikasi web saja. Selenium bisa digunakan untuk otomatisasi, semacam Macro, yang bisa digunakan untuk membuat otomatisasi pengisian form website.

Melalui kesempatan kali ini, kita akan menggunakan selenium untuk membuat aplikasi yang secara otomatis mencari keyword dan menghasilkan list ebook, lalu mendownloadnya otomatis tanpa perlu kita berinteraksi dengan halaman web tersebut.

Pertama, kita menggunakan tools Visual Studio 2022 Community Edition dan SDK .NET 9.0 dengan bahasa pemrograman C#. Target link website kita adalah https://libgen.bz/ atau https://libgen.gl/

MEMBUAT WINFORM PROJECT

Buka visual studio 2022, dan pilih template project Windows Form APP , perhatikan tanpa tulisan .NET Framework pada nama template projectnya agar supaya bisa menggunakan .NET 9.

Gambar 1 : Tampilan Create New Project pada Visual Studio 2022

Kemudian, pada bagian Project Name, isi dengan WinFormAppSelenium. Kemudian pada target framework, pilih dengan .NET 9. Lalu klik tombol Create.

Gambar 2: Dialog configure new project saat membuat project windows form baru di Visual Studio 2022

Kemudian pada Solution Explorer, pada Dependencies klik kanan lalu pilih Manage Nuget Packages. Cari nuget package terkait dengan Selenium.WebDriver.

Gambar 3 : Tampilan Manage Nuget Package untuk pencarian nuget pada Visual Studio 2022

Berikut ini adalah nuget package mandatory yang harus diinstall pada project :

  • Selenium.WebDriver
  • Selenium.Support
  • Selenium.WebDriver.MSEdgeDriver
  • Selenium.WebDriver.ChromeDriver
  • Selenium.WebDriver.Extensions
  • SeleniumExtras.WaitHelpers

Sebenarnya, selenium ini bisa memungkinkan untuk menggunakan berbagai macam browser tergantung dari driver apa yang kita install. Jika kita menginstall MSEdgeDriver maka kita menggunakan browser Edge windows untuk menjalankan otomatisasi. Namun jika kita menggunakan ChromeDriver maka kita akan menggunakan browser Chrome. Setiap browser tersebut merupakan turunan dari interface IWebDriver , sehingga implementasinya bisa kita ganti dengan nuget package yang kita inginkan.

Gambar 4: Tampilan List Nuget Package yang terinstall terkait kebutuhan Selenium Web Driver

Setelah semua nuget package yang diperlukan sudah terinstall, selanjutnya buka file Form1 dan buka dalam mode Form Desainer. Buatlah form dengan sebuah teksbox untuk inputan keyword pencarian, sebuah tombol download , dan sebuah label untuk menunjukkan progress dari proses yang berjalan sudah berapa persen.

Gambar 5: Tampilan windows form desainer di visual studio 2022 yang menampilkan desain form untuk download

Double click pada tombol buttonDownload. Lalu masukkan kode berikut ini. Kita menggunakan BackgroundWorker agar supaya proses Selenium yang sedang berjalan tidak melakukan blocking Thread dari windows form. Sehingga windows form bisa lebih responsif. Listing kode berikut ini adalah menambahkan event handler yang menghandle code ketika background worker sedang bekerja, sedang update progress, dan ketika sudah selesai berjalan. Mirip seperti callback dari proses async.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }


    private System.ComponentModel.BackgroundWorker bgWorker = null;
    private void buttonDownload_Click(object sender, EventArgs e)
    {
        buttonDownload.Visible = false;

        if(bgWorker == null)
        {
            bgWorker = new System.ComponentModel.BackgroundWorker();
        }
        
        bgWorker.DoWork += BgWorker_DoWork;
        bgWorker.RunWorkerCompleted += BgWorker_RunWorkerCompleted;
        bgWorker.ProgressChanged += BgWorker_ProgressChanged;
        bgWorker.WorkerSupportsCancellation = true;
        bgWorker.WorkerReportsProgress = true;
        bgWorker.RunWorkerAsync();

    }

    private void BgWorker_ProgressChanged(object? sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    private void BgWorker_RunWorkerCompleted(object? sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        throw new NotImplementedException();
    }

    private void BgWorker_DoWork(object? sender, System.ComponentModel.DoWorkEventArgs e)
    {
        throw new NotImplementedException();
    }
}

Untuk membuat sebuah proses otomatisasi selenium sangat mudah, pertama kita membuat object dari DriverOptions browser options, dalam hal ini EdgeOptions. EdgeOptions adalah class turunan dari DriverOptions. Kita juga perlu membuat object instance dari DriverService, dalam hal ini EdgeDriverService. Setelah kita memiliki options dan service, barulah kita bisa membuat new object dari implementasi interface IWebDriver, yaitu dengan membuat new object EdgeDriver. EdgeDriver ini merupakan webdriver yang akan kita panggil selama kita coding hingga akhir.

 var browserOptions = new EdgeOptions();
 browserOptions.UseWebView = false;
  
 var service = EdgeDriverService.CreateDefaultService();
 service.HideCommandPromptWindow = true;

 selenium = new EdgeDriver(service, browserOptions);
 selenium.Url = "https://libgen.bz/";
 selenium.Navigate();

Konsep dari otomatisasi nya adalah sederhana dan mirip dengan bagaimana DOM Html selama ini. Intinya kita harus mencari element HTML baik menggunakan Id, Name, CssClass, maupun TagName. Jika ketemu , hal pertama yang perlu kita ketahui adalah kita dapat mendapatkan info tentang tag HTML tersebut, baik attribute, text, css. Kedua, kita dapat mengirimkan key (Ketikan keyboard ke element HTML Input tersebut), atau kita dapat melakukan click mouse ke element HTML itu (jika bukan inputan).

Berikut ini adalah contoh potongan kode untuk menemukan form input, mengisi form input dengan teks secara otomatis, lalu mengklik tombol search secara otomatis. Perhatikan bagaimana kode berikut ini menemukan element HTML.

  var form = selenium.FindElement(By.Id("formlibgen"));
  var inputsearch = form.FindElement(By.Name("req"));
  inputsearch.SendKeys("artificial intelligence");

  var btnSearch = form.FindElement(By.Id("button-addon2"));
  btnSearch.Click();

Pada selenium , terdapat semacam Wait untuk sync thread yang menunggu suatu kondisi tertentu tercapai sehingga bisa baru lanjut ke proses selanjutnya. Wait ini sangat penting, karena memungkinkan kita menunggu elemen tertentu tampil, atau menunggu kondisi halaman web berubah sebelum potongan kode selanjutnya dieksekusi. Jika kita tidak menggunakan wait, bisa jadi kode kita berjalan padahal halaman web belum ready.

 var wait = new WebDriverWait(selenium, TimeSpan.FromSeconds(30));  wait.Until(ExpectedConditions.ElementIsVisible(By.TagName("body")));

Berikut adalah listing kode lengkap aplikasi selenium pada winform. Dari kode winform yang kita buat di awal, coding terkait selenium ini kita letakkan di dalam event handler background worker DoWork. Sehingga aktivitas selenium yang sangat lama dan panjang tidak akan membuat winform menjadi hang / tidak responsif UI nya.

using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
using OpenQA.Selenium.Support.UI;
using SeleniumExtras.WaitHelpers;

namespace WinFormsAppSelenium
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        private System.ComponentModel.BackgroundWorker bgWorker = null;
        private void buttonDownload_Click(object sender, EventArgs e)
        {
            buttonDownload.Visible = false;

            if (bgWorker == null)
            {
                bgWorker = new System.ComponentModel.BackgroundWorker();
            }

            bgWorker.DoWork += BgWorker_DoWork;
            bgWorker.RunWorkerCompleted += BgWorker_RunWorkerCompleted;
            bgWorker.ProgressChanged += BgWorker_ProgressChanged;
            bgWorker.WorkerSupportsCancellation = true;
            bgWorker.WorkerReportsProgress = true;
            bgWorker.RunWorkerAsync(textBoxKeyword.Text);

        }

        private void BgWorker_ProgressChanged(object? sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            labelProgress.Text = $"Progress : {e.ProgressPercentage} %";
        }

        private void BgWorker_RunWorkerCompleted(object? sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            buttonDownload.Visible = true;
            if (e.Result != null && ((bool)e.Result) == true)
            {
                MessageBox.Show("File downloaded !");
            }
        }

        private IWebDriver selenium;
        private void BgWorker_DoWork(object? sender, System.ComponentModel.DoWorkEventArgs e)
        {
            if (selenium != null)
            {
                selenium.Quit();
                selenium.Dispose();
                selenium = null;
            }
            try
            {
                var keyword = e.Argument as string ?? "artificial intelligence";

                bgWorker.ReportProgress(0);

                var downloadPath = System.IO.Path.Combine(Application.StartupPath, "DownloadResult", $"{DateTime.Now:yyMMddHHmmss}");
                if (!System.IO.Directory.Exists(downloadPath))
                {
                    System.IO.Directory.CreateDirectory(downloadPath);
                }

                string MAIN_URL_TO_VISIT = "https://libgen.bz/";

                var browserOptions = new EdgeOptions();
                browserOptions.UseWebView = false;
                browserOptions.AddArgument($"--app={MAIN_URL_TO_VISIT}");
                browserOptions.AddArgument("--start-maximized"); //
                browserOptions.AddUserProfilePreference("download.default_directory", downloadPath);
                browserOptions.AddUserProfilePreference("download.prompt_for_download", false); // To prevent the download prompt
                browserOptions.AddUserProfilePreference("download.directory_upgrade", true); // For newer Edge versions

                var service = EdgeDriverService.CreateDefaultService();
                service.HideCommandPromptWindow = true;

                selenium = new EdgeDriver(service, browserOptions);
                selenium.Url = MAIN_URL_TO_VISIT;
                selenium.Navigate();

                // new page
                var wait = new WebDriverWait(selenium, TimeSpan.FromSeconds(30));
                wait.Until(ExpectedConditions.ElementIsVisible(By.TagName("body")));
                Thread.Sleep(1000);
                bgWorker.ReportProgress(10);

                selenium.SwitchTo().DefaultContent();
                var form = selenium.FindElement(By.Id("formlibgen"));
                var inputsearch = form.FindElement(By.Name("req"));
                inputsearch.SendKeys(keyword);

                var btnSearch = form.FindElement(By.Id("button-addon2"));
                btnSearch.Click();

                bgWorker.ReportProgress(30);

                // new page
                wait.Until(ExpectedConditions.ElementIsVisible(By.TagName("body")));

                var tablelibgen = selenium.FindElement(By.Id("tablelibgen"));
                var trElements = tablelibgen.FindElements(By.TagName("tr"));
                var firstTR = trElements[1];
                var innerTD = firstTR.FindElements(By.TagName("td"));
                var actionTD = innerTD[8];
                var actionButton = actionTD.FindElements(By.TagName("a"));

                var action = actionButton.FirstOrDefault();
                action.Click();

                bgWorker.ReportProgress(60);

                // new page
                wait.Until(ExpectedConditions.ElementIsVisible(By.TagName("body")));

                var tableDownload = selenium.FindElement(By.Id("main"));
                var trDownload = tableDownload.FindElements(By.TagName("tr"));
                var tdDownload = trDownload[0].FindElements(By.TagName("td"));
                var linkDownload = tdDownload[1].FindElement(By.TagName("a"));
                linkDownload.Click();

                 wait = new WebDriverWait(selenium, TimeSpan.FromSeconds(10*60));
 wait.Until(drv =>
 {
     var files = System.IO.Directory.EnumerateFiles(downloadPath, "*.pdf");
     var files2 = System.IO.Directory.EnumerateFiles(downloadPath, "*.epub");
     var files3 = System.IO.Directory.EnumerateFiles(downloadPath, "*.azw3");
     return files.Count() > 0 || files2.Count() > 0 || files3.Count() > 0;
 });


                bgWorker.ReportProgress(100);


                e.Result = true;

                if (selenium != null)
                {
                    selenium.Quit();
                    selenium.Dispose();
                    selenium = null;
                }
            }
            catch (Exception)
            {
                e.Cancel = true;
                if (selenium != null)
                {
                    selenium.Quit();
                    selenium.Dispose();
                    selenium = null;
                }
            }

        }       
    }
}

MENJALAN APLIKASI SELENIUM

Untuk menjalankan aplikasi, paling sederhana dengan cara debug/F5 pada visual studio. Saat aplikasi berjalan, isikan kata kunci pencarian pada teksbox yang ada. Selanjutnya klik tombol Download.

Gambar 6: UI windows form untuk download

Ketika selenium berjalan, maka akan muncul window baru yang merupakan embedded browser dari edge. Browser ini akan tampil dan otomatis membuka halaman web. Biarkan saja window tersebut dan kita tidak perlu berinteraksi dengan window tersebut. Jangan melakukan click apapun di window browser itu.

Saat selenium running, maka halaman web yang muncul pada browser window akan otomatis terbuka dan diisi otomatis form inputnya. Halaman browser akan pindah alamat otomatis , mencari pdf berdasarkan keyword, hingga pada halaman terakhir yang memiliki link download akan melakukan download otomatis.

Gambar 7 : Halaman browser ketika selenium sedang running dan melakukan download otomatis.
Gambar 8: Tampilan ketika download otomatis.

KESIMPULAN

  • Selenium merupakan framework test automation yang sangat terkenal dan biasa digunakan untuk melakukan test automation ke halaman web yang sedang dikembangkan.
  • Karena sifatnya yang mendukung otomatisasi, maka selenium tidak hanya untuk web testing saja, tetapi bisa digunakan untuk otomatisasi ke halaman web.
  • Selenium memerlukan coding seperti layaknya DOM HTML, dan membutuhkan kecocokan terhadap element HTML di halaman web yang dicari. Jika terjadi kesalahan pencarian element HTML maka bisa dipastikan selenium akan mengalami error.

Download Source code di sini

,


Leave a Reply

Your email address will not be published. Required fields are marked *