148 65 8MB
English Pages [331] Year 2024
Selenium WebDriver Recipes in C# Practical Testing Solutions for Selenium WebDriver — Third Edition — Courtney Zhan, Edited by Zhimin Zhan
Selenium WebDriver Recipes in C# Practical Testing Solutions for Selenium WebDriver Third Edition
Courtney Zhan Zhimin Zhan
Selenium WebDriver Recipes in C#: Practical Testing Solutions for Selenium WebDriver, Third Edition Courtney Zhan Fitzgibbon, QLD, Australia
Zhimin Zhan Brisbane, QLD, Australia
ISBN-13 (pbk): 979-8-8688-0022-1 https://doi.org/10.1007/979-8-8688-0023-8
ISBN-13 (electronic): 979-8-8688-0023-8
Copyright © 2024 by Courtney Zhan, Edited by Zhimin Zhan This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights. While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made. The publisher makes no warranty, express or implied, with respect to the material contained herein. Managing Director, Apress Media LLC: Welmoed Spahr Acquisitions Editor: Melissa Duffy Development Editor: James Markham Coordinating Editor: Gryffin Winkler Copy Editor: Mary Behr Cover designed by eStudioCalamar Cover image by robert1029 from Pixabay (https://pixabay.com) Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY 10004, U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected], or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation. For information on translations, please e-mail [email protected]; for reprint, paperback, or audio rights, please e-mail [email protected]. Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales web page at www.apress.com/bulk-sales. Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub (https://github.com/Apress). For more detailed information, please visit https://www.apress.com/gp/services/source-code. Paper in this product is recyclable
This book is dedicated to my mum, Xindi.
Table of Contents About the Authors�����������������������������������������������������������������������������xvii Preface����������������������������������������������������������������������������������������������xix Chapter 1: Introduction������������������������������������������������������������������������1 Selenium WebDriver����������������������������������������������������������������������������������������������1 Selenium Language Bindings�������������������������������������������������������������������������������1 Set Up the Development Environment - Visual Studio Code���������������������������������4 Prerequisites���������������������������������������������������������������������������������������������������4 Set Up Visual Studio Code�������������������������������������������������������������������������������4 Cross-Browser Testing����������������������������������������������������������������������������������������11 Chrome����������������������������������������������������������������������������������������������������������11 Firefox�����������������������������������������������������������������������������������������������������������13 Safari�������������������������������������������������������������������������������������������������������������13 Edge��������������������������������������������������������������������������������������������������������������15 Internet Explorer��������������������������������������������������������������������������������������������15 Visual Studio Unit Testing Framework����������������������������������������������������������������15 Visual Studio Unit Testing Framework Fixtures���������������������������������������������18 Alternative Framework: NUnit�����������������������������������������������������������������������������19 Run Recipe Scripts����������������������������������������������������������������������������������������������20
v
Table of Contents
Run Test(s) in VS Code����������������������������������������������������������������������������������������20 Find the Test Case�����������������������������������������������������������������������������������������20 Run an Individual Test Case���������������������������������������������������������������������������21 Run All Test Cases in a Test Script File����������������������������������������������������������22 Run Tests from the Command Line����������������������������������������������������������������23
Chapter 2: Locating Web Elements�����������������������������������������������������25 Start a Browser���������������������������������������������������������������������������������������������������26 Inspect a Web Element in a Browser�������������������������������������������������������������27 Find an Element by ID������������������������������������������������������������������������������������28 Find an Element by Name������������������������������������������������������������������������������28 Find an Element by Link Text�������������������������������������������������������������������������29 Find an Element by Partial Link Text��������������������������������������������������������������29 Find an Element by XPath������������������������������������������������������������������������������29 Find an Element by a Tag Name��������������������������������������������������������������������31 Find an Element by Class������������������������������������������������������������������������������31 Find an Element by CSS Selector������������������������������������������������������������������32 Find an Element by Relative Locators�����������������������������������������������������������32 Chain FindElement to Find Child Elements����������������������������������������������������33 Find Multiple Elements����������������������������������������������������������������������������������34 Locate a Web Element That Disappears After Inspect�����������������������������������34
Chapter 3: Hyperlink���������������������������������������������������������������������������37 Click a Link by Text���������������������������������������������������������������������������������������������37 Click a Link by ID�������������������������������������������������������������������������������������������������38 Click a Link by Partial Text����������������������������������������������������������������������������������38 Click a Link by XPath�������������������������������������������������������������������������������������������38 Click the Nth Link with Exact Same Label����������������������������������������������������������40
vi
Table of Contents
Click the Nth Link by CSS Selector���������������������������������������������������������������������40 Verify If a Link Is Present or Not��������������������������������������������������������������������������41 Get Link Data Attributes��������������������������������������������������������������������������������������41 Test If a Link Opens a New Browser Window������������������������������������������������������42
Chapter 4: Button�������������������������������������������������������������������������������43 Click a Button by Text������������������������������������������������������������������������������������������44 Click a Form Button by Text��������������������������������������������������������������������������������44 Submit a Form����������������������������������������������������������������������������������������������������44 Click a Button by ID���������������������������������������������������������������������������������������������45 Click a Button by Name���������������������������������������������������������������������������������������46 Click an Image Button�����������������������������������������������������������������������������������������46 Click a Button via JavaScript������������������������������������������������������������������������������47 Assert If a Button Is Present�������������������������������������������������������������������������������47 Assert If a Button Is Enabled or Disabled������������������������������������������������������������47
Chapter 5: TextField and TextArea������������������������������������������������������49 Enter Text into a Text Field by Name�������������������������������������������������������������������50 Enter Text into a Text Field by ID�������������������������������������������������������������������������50 Enter Text into a Password Field�������������������������������������������������������������������������50 Clear a Text Field�������������������������������������������������������������������������������������������������50 Enter Text into a Multiline Text Area��������������������������������������������������������������������51 Assert a Value�����������������������������������������������������������������������������������������������������51 Focus on a Control����������������������������������������������������������������������������������������������51 Set a Value to a Read-Only or Disabled Text Field����������������������������������������������52 Set and Assert the Value of a Hidden Field���������������������������������������������������������53
vii
Table of Contents
Chapter 6: Radio Button���������������������������������������������������������������������55 Select a Radio Button������������������������������������������������������������������������������������������55 Clear the Radio Option Selection������������������������������������������������������������������������56 Assert a Radio Option Is Selected�����������������������������������������������������������������������57 Iterate Radio Buttons in a Radio Group���������������������������������������������������������������57 Click the Nth Radio Button in a Group�����������������������������������������������������������������58 Click a Radio Button by the Following Label�������������������������������������������������������58 Customized Radio Buttons with iCheck��������������������������������������������������������������59
Chapter 7: CheckBox��������������������������������������������������������������������������61 Check by Name���������������������������������������������������������������������������������������������������61 Check by Id���������������������������������������������������������������������������������������������������������61 Uncheck a Checkbox�������������������������������������������������������������������������������������������62 Assert a Checkbox Is Checked (or Not)���������������������������������������������������������������62 Chain FindElement to Find Child Elements���������������������������������������������������������62 Customized Checkboxes using iCheck���������������������������������������������������������������63
Chapter 8: Select List�������������������������������������������������������������������������65 Import Selenium.Support������������������������������������������������������������������������������������65 Select an Option by Text��������������������������������������������������������������������������������������66 Select an Option by a Value��������������������������������������������������������������������������������67 Select an Option by an Index������������������������������������������������������������������������������67 Send Keys to the Select Element������������������������������������������������������������������������67 Select an Option by Iterating All Options�������������������������������������������������������������68 Select Multiple Options���������������������������������������������������������������������������������������68 Clear One Selection���������������������������������������������������������������������������������������������69 Clear All Selections���������������������������������������������������������������������������������������������70
viii
Table of Contents
Assert a Selected Option�������������������������������������������������������������������������������������70 Assert a Label or Value of a Select List���������������������������������������������������������������70 Assert Multiple Selections����������������������������������������������������������������������������������71
Chapter 9: Navigation and Browser����������������������������������������������������73 Go to a URL���������������������������������������������������������������������������������������������������������73 Visit Pages Within a Site�������������������������������������������������������������������������������������73 Open Browser in a Certain Size��������������������������������������������������������������������������75 Maximize the Browser Window���������������������������������������������������������������������������75 Move the Browser Window���������������������������������������������������������������������������������75 Minimize a Browser Window�������������������������������������������������������������������������������76 Scroll Focus to Control via JavaScript����������������������������������������������������������������76 Scroll with Scroll Wheel Actions�������������������������������������������������������������������������77 Switch Between Browser Windows or Tabs��������������������������������������������������������78 New Browser Window or Tab������������������������������������������������������������������������������79 Open and Close Browser Tabs Using JavaScript�������������������������������������������������79 Remember Current Web Page URL and Come Back to It Later���������������������������80
Chapter 10: Assertion�������������������������������������������������������������������������83 Assert a Page Title����������������������������������������������������������������������������������������������83 Assert Page Text��������������������������������������������������������������������������������������������������83 Assert the Page Source���������������������������������������������������������������������������������������84 Assert Label Text�������������������������������������������������������������������������������������������������84 Assert Span Text�������������������������������������������������������������������������������������������������85 Assert Div Text or HTML��������������������������������������������������������������������������������������85 Assert Table Text�������������������������������������������������������������������������������������������������86 Assert Text in a Table Cell�����������������������������������������������������������������������������������88
ix
Table of Contents
Assert Text in a Table Row����������������������������������������������������������������������������������88 Assert If an Image Is Present������������������������������������������������������������������������������88 Assert Element Location and Width��������������������������������������������������������������������88 Assert Element CSS Style�����������������������������������������������������������������������������������89 Assert JS Errors on a Web Page��������������������������������������������������������������������������89
Chapter 11: Frames����������������������������������������������������������������������������91 Testing Frames����������������������������������������������������������������������������������������������������91 Find a Frame with FindElement��������������������������������������������������������������������������93 Test an IFrame����������������������������������������������������������������������������������������������������93 Test Multiple IFrames������������������������������������������������������������������������������������������95
Chapter 12: Testing AJAX�������������������������������������������������������������������97 Pause for a Specific Duration of Time�����������������������������������������������������������������98 Explicit Waits Until Time Out�������������������������������������������������������������������������������99 Implicit Waits Until Time Out�����������������������������������������������������������������������������100 Fluent Waits Until Time Out�������������������������������������������������������������������������������100 Create Your Own Polling Check Function����������������������������������������������������������101 Refactor with a Reusable Function�������������������������������������������������������������������102 Wait for the AJAX Call to Complete Using JQuery���������������������������������������������104
Chapter 13: File Upload and Popup Dialogs��������������������������������������107 File Upload��������������������������������������������������������������������������������������������������������107 File Upload with a Relative Path�����������������������������������������������������������������������109 JavaScript Popups��������������������������������������������������������������������������������������������109 Handle JavaScript Popups Using Alert API��������������������������������������������������110 Handle JavaScript Popups with JavaScript�������������������������������������������������111 Modal Style Dialogs������������������������������������������������������������������������������������������111
x
Table of Contents
Timeout on an Operation�����������������������������������������������������������������������������������112 Popup Handler Approach����������������������������������������������������������������������������������112 Basic or Proxy Authentication Dialog����������������������������������������������������������������113 Bypass Basic Authentication by Embedding the Username and Password in the URL�����������������������������������������������������������������������������������������115 Internet Explorer Modal Dialog�������������������������������������������������������������������������116
Chapter 14: Debugging Test Scripts�������������������������������������������������117 Print Text for Debugging������������������������������������������������������������������������������������117 Write the Page Source or Element HTML into a File�����������������������������������������118 Take a Screenshot���������������������������������������������������������������������������������������������118 Leave the Browser Open After a Test Finishes��������������������������������������������������119 Debug Test Execution using Debuggers������������������������������������������������������������120 Enable Breakpoints��������������������������������������������������������������������������������������120 Execute One Test Case in Debugging Mode������������������������������������������������121 Step Over Test Execution�����������������������������������������������������������������������������122
Chapter 15: Test Data�����������������������������������������������������������������������123 Get Data Dynamically����������������������������������������������������������������������������������������123 Get a Random Boolean Value����������������������������������������������������������������������������125 Get a Random Boolean Value with Timestamps������������������������������������������������126 Generate a Number Within a Range������������������������������������������������������������������127 Get a Random Character�����������������������������������������������������������������������������������127 Get a Random String at a Fixed Length������������������������������������������������������������127 Get a Random String in a Collection�����������������������������������������������������������������128 Generate a Test File at a Fixed Size������������������������������������������������������������������129 Retrieve Data from a Database�������������������������������������������������������������������������129
xi
Table of Contents
Chapter 16: Browser Profile and Capabilities�����������������������������������133 Get Browser Type and Version��������������������������������������������������������������������������133 Set the Page Load Strategy������������������������������������������������������������������������������134 Set an HTTP Proxy for a Browser����������������������������������������������������������������������135 Verify File Download in Chrome������������������������������������������������������������������������136 Verify File Download in Firefox�������������������������������������������������������������������������136 Bypass Basic Authentication with the Firefox AutoAuth Plugin������������������������137 Manage Cookies������������������������������������������������������������������������������������������������140 Headless Browser Testing with Chrome�����������������������������������������������������������141 Test Responsive Websites���������������������������������������������������������������������������������142
Chapter 17: Advanced User Interactions������������������������������������������145 Double-Click a Control��������������������������������������������������������������������������������������146 Move the Mouse to a Control (Mouse Over)������������������������������������������������������146 Click and Hold (Select Multiple Items)��������������������������������������������������������������147 Context Click (Right-Click a Control)�����������������������������������������������������������������148 Drag-and-Drop��������������������������������������������������������������������������������������������������148 Drag a Slider�����������������������������������������������������������������������������������������������������150 Send Key Sequences (Select All and Delete)����������������������������������������������������151
Chapter 18: HTML5 and JavaScript��������������������������������������������������153 HTML5 Email Type Field������������������������������������������������������������������������������������153 HTML5 Time Field���������������������������������������������������������������������������������������������154 Invoke the onclick JavaScript Event�����������������������������������������������������������������155 Invoke JavaScript Events Such As OnChange���������������������������������������������������156 Scroll to the Bottom of a Page��������������������������������������������������������������������������157 Chosen - Standard Select���������������������������������������������������������������������������������157 Chosen - Multiple Select�����������������������������������������������������������������������������������161
xii
Table of Contents
AngularJS Web Pages���������������������������������������������������������������������������������������166 Ember JS Web Pages����������������������������������������������������������������������������������������169 Faking Geolocation with JavaScript������������������������������������������������������������������171 Save an SVG Chart to a PNG Image�������������������������������������������������������������������172 Save a Canvas to a PNG Image�������������������������������������������������������������������������172
Chapter 19: WYSIWYG HTML Editors�������������������������������������������������175 TinyMCE������������������������������������������������������������������������������������������������������������175 CKEditor������������������������������������������������������������������������������������������������������������177 SummerNote�����������������������������������������������������������������������������������������������������178 CodeMirror��������������������������������������������������������������������������������������������������������179
Chapter 20: Leveraging Programming����������������������������������������������181 Throw Exceptions to Fail Tests��������������������������������������������������������������������������181 Ignorable Test Statement Error�������������������������������������������������������������������������183 Read an External File����������������������������������������������������������������������������������������184 Data-Driven Tests with Excel����������������������������������������������������������������������������185 Data-Driven Tests with CSV������������������������������������������������������������������������������189 Identify Element IDs with Dynamically Generated Long Prefixes����������������������190 Sending Special Keys Such as Enter to an Element or Browser�����������������������191 Use of Unicode in Test Scripts���������������������������������������������������������������������������192 Extract a Group of Dynamic Data: Verify Search Results in Order���������������������193 Verify Uniqueness of a Set of Data��������������������������������������������������������������������195 Extract Dynamic Visible Data Rows from a Results Table���������������������������������195 Extract Dynamic Text Following a Pattern Using Regex������������������������������������198
Chapter 21: Optimization������������������������������������������������������������������201 Assert Text in a Page Source Is Faster Than the Text����������������������������������������201 Getting Text From a More Specific Element Is Faster���������������������������������������202 xiii
Table of Contents
Avoid Programming If-Else Blocks If Possible��������������������������������������������������203 Use a Variable to Cache Unchanged Data���������������������������������������������������������204 Enter Large Text into a Text Box������������������������������������������������������������������������205 Use Environment Variables to Change Test Behaviors Dynamically������������������205 Testing a Web Site in Multiple Languages��������������������������������������������������������207 Multi-Language Testing with Lookups��������������������������������������������������������������209
Chapter 22: Gotchas�������������������������������������������������������������������������213 Test Starts Browser But No Execution but a Blank Screen�������������������������������213 Failed to Assert Copied Text in Browser������������������������������������������������������������215 The Same Test Works for Chrome, But Not for IE����������������������������������������������217 “unexpected tag name ‘input’”�������������������������������������������������������������������������218 Element Is Not Clickable or Visible��������������������������������������������������������������������219
Chapter 23: Selenium 4��������������������������������������������������������������������221 Chrome For Testing�������������������������������������������������������������������������������������������221 New Browser Window or Tab����������������������������������������������������������������������������224 Basic Authentication via Register���������������������������������������������������������������������224 Print to PDF�������������������������������������������������������������������������������������������������������225 Save Element Screenshot���������������������������������������������������������������������������������226 Drive Elements Inside a Shadow DOM��������������������������������������������������������������226 Relative Locators����������������������������������������������������������������������������������������������229 Get the Element on the Right of a Checkbox�����������������������������������������������229 Get the Element(s) on the Left of a Checkbox���������������������������������������������230 Above in a Table�������������������������������������������������������������������������������������������231 Below in a Table������������������������������������������������������������������������������������������233 Near�������������������������������������������������������������������������������������������������������������235 Summary�����������������������������������������������������������������������������������������������������237
xiv
Table of Contents
Chapter 24: Selenium DevTools��������������������������������������������������������239 Emulate Browser Crash������������������������������������������������������������������������������������240 CDP Send Command�����������������������������������������������������������������������������������������241 Emulate GEO Location���������������������������������������������������������������������������������242 Emulate Locale�������������������������������������������������������������������������������������������������243 Emulate Timezone���������������������������������������������������������������������������������������������244 Network Interception����������������������������������������������������������������������������������������244 Network Latency�����������������������������������������������������������������������������������������������245 Security: Ignore CertificateErrors����������������������������������������������������������������������247
Chapter 25: Selenium Grid����������������������������������������������������������������249 Selenium Server Standalone����������������������������������������������������������������������������250 Execute Tests on a Remote Machine����������������������������������������������������������������250 Set Up Selenium Grid����������������������������������������������������������������������������������������251 Using Selenium Grid to Run Tests���������������������������������������������������������������������254 Issues with Selenium Grid��������������������������������������������������������������������������������256
Chapter 26: Continuous Testing��������������������������������������������������������261 CI vs. CT������������������������������������������������������������������������������������������������������������263 Preparation�������������������������������������������������������������������������������������������������������264 Source Control Test Scripts in Git����������������������������������������������������������������������264 Compile Test Scripts������������������������������������������������������������������������������������265 Execute a Test Script from the Command Line��������������������������������������������266 Execute a Test Script with JUnit XML����������������������������������������������������������267 Set Up BuildWise Server�����������������������������������������������������������������������������������268 Set Up a Build Project���������������������������������������������������������������������������������������270 Run a Suite of C# tests in BuildWise�����������������������������������������������������������������272 What’s the Magic?��������������������������������������������������������������������������������������������273
xv
Table of Contents
Chapter 27: Case Studies������������������������������������������������������������������275 Verify Chart Generation�������������������������������������������������������������������������������������275 Test Design��������������������������������������������������������������������������������������������������275 Test Steps����������������������������������������������������������������������������������������������������276 Test Script����������������������������������������������������������������������������������������������������280 Drawing on a Canvas����������������������������������������������������������������������������������������281 Test Steps����������������������������������������������������������������������������������������������������282 Test Script����������������������������������������������������������������������������������������������������285 Automated Testing Elements on a Lazy Load Page�������������������������������������������287 Test Design��������������������������������������������������������������������������������������������������288 Test Steps����������������������������������������������������������������������������������������������������288 Generate a User Guide with an Automation Script��������������������������������������������290 Test Design��������������������������������������������������������������������������������������������������290 Test Steps����������������������������������������������������������������������������������������������������291 Generated Files��������������������������������������������������������������������������������������������293 What Does It Look Like?������������������������������������������������������������������������������294 Summary�����������������������������������������������������������������������������������������������������294 Broken Link Checker�����������������������������������������������������������������������������������������295 Test Design��������������������������������������������������������������������������������������������������295 Test Steps����������������������������������������������������������������������������������������������������295
Afterword������������������������������������������������������������������������������������������299 Resources�����������������������������������������������������������������������������������������303 Appendix 1: Visual Studio IDE Setup������������������������������������������������307 Appendix 2: Visual Studio IDE Debugging Test Execution����������������319 Index�������������������������������������������������������������������������������������������������323
xvi
About the Authors Courtney Zhan is a software development engineer at Amazon Australia. She is passionate about programming, end-to-end test automation, continuous testing, and graphic design. She shares tips and guides on test automation and continuous testing weekly on Medium at courtneyzhan.medium.com.
Zhimin Zhan is the founder and CTO of AgileWay Pty Ltd, Australia. As an advisor and coach, he helps organizations implement continuous testing with open technologies such as Selenium WebDriver and Appium. Zhimin is the creator of the TestWise Testing IDE and international award-winning BuildWise CT Server and an author.
xvii
Preface It has been nearly eight years since Selenium WebDriver Recipes for C# Third Edition was published. Since then, •
Selenium WebDriver v2 → v4
•
Visual Studio 2013 → 2022
•
The uprising of VS Code
•
Browser market changes mean IE and Edge (classic) are gone.
It is about time to update this book. There is one observation we want to point out. Before starting this edition, we opened the recipes and ran all tests in Visual Studio 2022, and 138 out of 171 tests passed. Please note this was Selenium WebDriver v2 (from 8 years ago) running against the latest Chrome browser (v114). The majority of the test failures were related to the changes in external websites and Firefox tests (which were not configured). This shows the high stability of WebDriver.
What’s New Selenium’s new features and improvements include the following: •
DOM shadow roots
•
Relative locators
•
Chrome DevTools
xix
Preface
•
New APIs
•
…and more!
What’s new in this book: •
New (about 15% more) and updated recipes
•
Using Visual Studio Code as the tool for developing/ executing test scripts
•
Executing Selenium C# tests in a BuildWise continuous testing server
Who Should Read This Book This book is for software testers or programmers who are writing (or want to learn how to write) automated tests with Selenium WebDriver. To get the most out of this book, basic C# coding skill is required.
How to Read This Book Typically, a recipe book serves as a reference, allowing readers to navigate directly to the specific topic of interest. For instance, if you encounter a challenge while testing a multiple select list and require guidance, you can refer to the Table of Contents and locate the relevant chapter. This book supports this style of reading. Since the recipes are arranged according to their levels of complexity, you will also be able to work through the book from the front to back if you are looking to learn test automation with Selenium WebDriver.
xx
Preface
Recipe Test Scripts To help you learn more effectively, this book has a dedicated site1 that contains the recipe test scripts and related resources. As the old saying goes, “There’s more than one way to skin a cat.” When it comes to achieving the desired testing outcomes, there are often multiple approaches. The recipe test scripts in this book are written for simplicity, so there is always room for improvement. But for many, understanding the solution quickly and getting the job done are probably more important. If you have a better and simpler way, please let us know. All recipe test scripts are Selenium WebDriver 4 compliant and can be executed on Chrome, Firefox, and Edge on multiple platforms.
Send Us Feedback We appreciate your comments, suggestions, and reports on errors in the book and the recipe test scripts. You may submit your feedback on the book site. Courtney Zhan and Zhimin Zhan September 2023
http://zhimin.com/books/selenium-recipes-csharp
1
xxi
CHAPTER 1
Introduction Selenium WebDriver is a free and open-source library for automating web applications. Basically, you can use it to drive web apps in a browser and for testing purposes.
Selenium WebDriver Selenium WebDriver is a merger of Selenium v1 and another automation framework called WebDriver led by Simon Stewart at Google. (Simon later joined Facebook and Apple.) Selenium 2.0 was released in July 2011. We use “Selenium,” “WebDriver,” and “Selenium WebDriver” interchangeably in this book. Selenium v3 and v4 were released in October of 2016 and October of 2021, respectively.
Selenium Language Bindings Selenium scripts can be written in multiple programming languages such as Java, C#, JavaScript, Python, and Ruby (the core ones). All examples in this book are written in Selenium with C# binding. As you will see in the examples below, the use of Selenium in different bindings is very similar. Once you master one, you can apply it to others quite easily. Take a look at a simple Selenium test script in four different language bindings: C#, Java, Python, and Ruby.
© Courtney Zhan, Edited by Zhimin Zhan 2024 C. Zhan, Selenium WebDriver Recipes in C#, https://doi.org/10.1007/979-8-8688-0023-8_1
1
Chapter 1
Introduction
C#: using using using using
System; Microsoft.VisualStudio.TestTools.UnitTesting; OpenQA.Selenium; OpenQA.Selenium.Chrome;
class GoogleSearch { static void Main() { // Create a new instance of the driver IWebDriver driver = new ChromeDriver(); // And now use this to visit Google driver.Navigate().GoToUrl("http://www.google.com"); // Find the text input element by its name IWebElement query = driver.FindElement(By.Name("q")); // Enter something to search for query.SendKeys("Hello Selenium WebDriver!"); // Submit the form based on an element in the form query.Submit(); // Check the title of the page Console.WriteLine(driver.Title); } } Java: import import import import 2
org.openqa.selenium.By; org.openqa.selenium.WebDriver; org.openqa.selenium.WebElement; org.openqa.selenium.firefox.FirefoxDriver;
Chapter 1
Introduction
public class GoogleSearch { public static void main(String[] args) { WebDriver driver = new FirefoxDriver(); driver.get("http://www.google.com"); WebElement element = driver.findElement(By.name("q")); element.sendKeys("Hello Selenium WebDriver!"); element.submit(); System.out.println("Page title is: " + driver.getTitle()); } } Python: from selenium import webdriver driver = webdriver.Firefox() driver.get("http://www.google.com") elem = driver.find_element_by_name("q") elem.send_keys("Hello WebDriver!") elem.submit() print(driver.title) Ruby: require "selenium-webdriver" driver = Selenium::WebDriver.for :chrome driver.navigate.to "http://www.google.com" element = driver.find_element(:name, 'q') element.send_keys "Hello Selenium WebDriver!" element.submit puts driver.title
3
Chapter 1
Introduction
et Up the Development Environment S Visual Studio Code Both the free Visual Studio Code (VS Code, for short) and the traditional Visual Studio IDE (Community or Enterprise edition) can be used to develop and execute C# Selenium tests. VS Code is a popular, if not the most popular, code editor and is more lightweight than the Visual Studio IDE. The Visual Studio IDE is better suited for development work. If you are only doing testing, VS Code is more than enough. We will use VS Code in this book. If you would like to use Visual Studio IDE, see the Appendix for setup instructions.
Prerequisites •
Download and install VS Code.
•
A browser, such as Chrome or Firefox
•
Have the browser’s driver (such as the ChromeDriver executable) included in the PATH.
Set Up Visual Studio Code 1. Install the .NET SDK. Download it from https://dotnet.microsoft.com/ en-us/download/dotnet/7.01. Note that .NET SDK now works on all major platforms. We chose macOS X64 since we were using a Mac. Obviously, it works on Windows too.
https://dotnet.microsoft.com/en-us/download/dotnet/7.0
1
4
Chapter 1
Introduction
Run the installer (Figure 1-1).
Figure 1-1. .NET SDK Installer screenshot Verify it was installed correctly by running this code in a new terminal window: $ dotnet --version 7.0.202 2. Install the C# and NuGet package manager extensions into VS Code. Click the Extensions tab on the left pane in VS Code (or use Command + Shift + X on a Mac or Control + Shift + X on Windows). Search for C# in the Extension Marketplace. This will add support for C# in VS Code. Install it (Figure 1-2).
Figure 1-2. Visual Studio Code’s C# extension 5
Chapter 1
Introduction
Repeat the same process for the NuGet Package Manager, which helps to add libraries, such as Selenium WebDriver, to test projects (Figure 1-3).
Figure 1-3. Visual Studio Code’s NuGet Package Manager extension 3. Create a MSTest project folder. The MSTest framework is a test framework which is included by default with Microsoft Visual Studio. From the terminal, run the following command to create a project named HelloSeleniumTest: $ dotnet new mstest -o HelloSeleniumTest Sample output: The template "MSTest Test Project" was created successfully. Processing post-creation actions... Restoring /Users/courtney/tmp/ HelloSeleniumTest/HelloSeleniumTest.csproj: Determining projects to restore... Restored /Users/courtney/tmp/HelloSeleniumTest/ HelloSeleniumTest.csproj (in 1.16 sec). Restore succeeded. 6
Chapter 1
Introduction
4. Open the newly created test project folder in VS Code. Run the (empty) test case by clicking the Run Test link, as indicated in Figure 1-4.
Figure 1-4. How to run an empty test in Visual Studio Code There is an extra compilation step, which was taken care of by VS Code, for readers who have only used scripting languages, such as Ruby and Python, as C# is a compiled language. As you can see, HelloSeleniumTest.dll is the output of the compilation (a.k.a. build). This empty test case is meaningless, but if it passes, it means your MSTest setup (with SDK) is correct.
7
Chapter 1
Introduction
5. Add the Selenium WebDriver package to the test project. You want to run a Selenium C# test that drives a Chrome browser (on macOS). There are three prerequisites: •
The Chrome browser
•
The ChromeDriver for the matching browser version is in the PATH
•
The Selenium WebDriver library must be installed and configured in the test project.
The first two are generic and needed for any WebDriverpowered automation. The third one you can achieve with the NuGet package manager. Press Command + Shift + P on Mac (or Control + Shift + P on Windows) to start the Command Palette, type NuGet, and select the NuGet Package Manager: Add Package option, as shown in Figure 1-5.
Figure 1-5. Executing NuGet Package Manager’s Add Package command in Visual Studio Code Then type in Selenium and press the Enter key (Figure 1-6).
8
Chapter 1
Introduction
Figure 1-6. Adding the package Selenium.WebDriver in Visual Studio Code Press the Enter key to select Selenium.WebDriver. Then select the latest version (in our case, 4.8.2). See Figure 1-7.
Figure 1-7. Selecting Selenium.WebDriver’s package version in Visual Studio Code After that, you will see popups at the right bottom of VS Code (Figure 1-8).
Figure 1-8. Prompt to restore unresolved dependencies in Visual Studio Code Click the Restore button. 9
Chapter 1
Introduction
6. First Selenium C# test Add a new file, LoginTest.cs, to the project (in VS Code). Paste in this content: namespace HelloSeleniumTest; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; [TestClass] public class SeleniumLoginOkTest { IWebDriver driver = null; [TestMethod] public void TestLoginOK() { driver = new ChromeDriver(); driver.Navigate().GoToUrl("http://travel. agileway.net"); driver.FindElement(By.Name("username")). SendKeys("agileway"); driver.FindElement(By.Name("password")). SendKeys("testwise"); driver.FindElement(By.Name("password")). Submit(); Assert.IsTrue(driver.PageSource. Contains("Signed in!")); driver.Quit(); } } Run it (as shown earlier in Step 4). You will see a Chrome browser launch and log into the AgileTravel site.
10
Chapter 1
Introduction
Cross-Browser Testing One big advantage of Selenium WebDriver over other web automation frameworks, in our opinions, is that it supports all major web browsers: Chrome, Safari, Microsoft Edge, and Firefox. To be more precise, all major browser vendors support WebDriver, a W3C standard. The browser market nowadays is more diversified (based on the StatsCounter2, the usage shares in May 2023 for Chrome, Safari, Edge, and Firefox are 66.0%, 12.8%, 9.9%, and 5.3%, respectively). It is logical that all external facing web sites require serious cross-browser testing. Selenium is a natural choice for this purpose because it far exceeds other web automation tools and frameworks.
Chrome To run Selenium tests in Google Chrome, besides the Chrome browser itself, ChromeDriver3 needs to be installed. Visit https://chromedriver. chromium.org/downloads4 and choose a version that matches your browser (Figure 1-9).
http://gs.statcounter.com/ http://chromedriver.storage.googleapis.com/ 4 https://chromedriver.chromium.org/downloads 2 3
11
Chapter 1
Introduction
Figure 1-9. ChromeDriver downloads page Download the one for your target platform, unzip it, and put the chromedriver executable in your PATH. To verify the installation, open a command window, execute the command chromedriver –version. You should see something like Figure 1-10.
Figure 1-10. Verifying the ChromeDriver version via the command line The following code launches a new Chrome browser window and closes it one second later: namespace HelloSeleniumTest; using System; using OpenQA.Selenium; using OpenQA.Selenium.Chrome; public class HelloSelenium { public static void main(String[] args) { IWebDriver driver = new ChromeDriver(); System.Threading.Thread.Sleep(1000);
12
Chapter 1
Introduction
driver.Quit(); } } C# beginners might be confused/frustrated when running this simple code snippet, with issues related to “project,” “namespace,” and “compiling.” Don't worry. We will cover the test execution shortly. For readers who have used a good scripting language such as Ruby: Yes, test automation with Ruby is a lot easier.
F irefox Selenium for Firefox requires geckodriver5. The following test script will open a web site in a new Firefox window: using OpenQA.Selenium.Firefox; // ... IWebDriver driver = new FirefoxDriver();
S afari Safari is the default macOS web browser. While Safari supports WebDriver out of the box, you will need to do minor setup to enable automation. 1. Enable Developer Tools in Safari. Open Safari’s Preferences (Safari ➤ Settings on the top bar or Command + ,). In the Advanced tab, check the “Show Develop menu in menu bar” box. See Figure 1-11.
https://github.com/mozilla/geckodriver
5
13
Chapter 1
Introduction
Figure 1-11. Enabling the Develop menu in Safari’s settings You should see the Develop menu in the top bar of Safari now. 2. Enable Remote Automation in Safari. Under the Develop menu tab, check the “Allow Remote Automation” option (Figure 1-12).
Figure 1-12. Enabling Remote Automation in Safari’s menu bar using OpenQA.Selenium.Safari; // ... IWebDriver driver = new SafariDriver(); 14
Chapter 1
Introduction
E dge Edge is Microsoft’s new default web browser on Windows 10+. The current Edge is based on Chromium (the legacy version was deprecated in March 2021). To drive Edge with WebDriver, you need Microsoft Edge WebDriver6. The installation process is the same as ChromeDriver, and the file is msedgedriver.exe. using System.IO; using OpenQA.Selenium.Edge; // ... IWebDriver driver = new EdgeDriver();
I nternet Explorer Internet Explorer has retired. In a rare case that you need to test a certain website against IE, it is still possible. Selenium requires IEDriverServer to drive IE browser. Its installation process is very similar to ChromeDriver. IEDriverServer is available at https://www.selenium.dev/downloads7. Choose the right one based on your Windows version (32- or 64-bit). using OpenQA.Selenium.IE; //... IWebDriver driver = new InternetExplorerDriver();
Visual Studio Unit Testing Framework The script examples above drive browsers. Strictly speaking, they are not tests (Selenium is an automation framework). To make the effective use of Selenium scripts for testing, you need to put them in a test framework that https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ www.selenium.dev/downloads
6 7
15
Chapter 1
Introduction
defines test structures and provides assertions (performing checks in test scripts). Here is an example using Visual Studio Unit Testing Framework: using using using using using using using using using
System; Microsoft.VisualStudio.TestTools.UnitTesting; OpenQA.Selenium; OpenQA.Selenium.Firefox; OpenQA.Selenium.IE; OpenQA.Selenium.Chrome; OpenQA.Selenium.Edge; OpenQA.Selenium.Safari; System.Collections.ObjectModel;
[TestClass] public class GoogleSearchDifferentBrowsersTest { [TestMethod] public void TestInIE() { IWebDriver driver = new InternetExplorerDriver(); driver.Navigate().GoToUrl("https://agileway.com. au/demo"); System.Threading.Thread.Sleep(1000); driver.Quit(); } [TestMethod] public void TestInFirefox() { IWebDriver driver = new FirefoxDriver(); driver.Navigate().GoToUrl("https://agileway.com. au/demo"); System.Threading.Thread.Sleep(1000); driver.Quit(); }
16
Chapter 1
Introduction
[TestMethod] public void TestInChrome() { IWebDriver driver = new ChromeDriver(); driver.Navigate().GoToUrl("https://agileway.com. au/demo"); System.Threading.Thread.Sleep(1000); driver.Quit(); } [TestMethod] public void TestInSafari() { IWebDriver driver = new SafariDriver(); driver.Navigate().GoToUrl("https://agileway.com. au/demo"); System.Threading.Thread.Sleep(1000); driver.Quit(); } [TestMethod] public void TestInEdge() { // Default option, MicrosoftWebDriver.exe must be in PATH IWebDriver driver = new EdgeDriver(); driver.Navigate().GoToUrl("https://agileway.com. au/demo"); System.Threading.Thread.Sleep(1000); driver.Quit(); } }
17
Chapter 1
Introduction
[TestMethod] annotates a test case below, in a format of TestCapitalCase. You will find more about VS Unit Test Framework from its home page8. However, we honestly don’t think it is necessary. The part used for test scripts is not much and is quite intuitive. After studying and trying out some examples, you will be quite comfortable with it.
Visual Studio Unit Testing Framework Fixtures If you worked with xUnit before, you must know the setUp() and tearDown() fixtures, which are called before or after every test. In VS Unit Test Framework, by using annotations ([ClassInitialize], [TestInitialize], [TestCleanup], and [ClassCleanup]), you can choose the name for the fixtures. Here is an example: [ClassInitialize] public static void BeforeAll() { // run before all test cases } [TestInitialize] public void Before() { // run before each test case } [TestMethod] public void TestCase1() { // one test case }
http://msdn.microsoft.com/en-us/library/ms243147
8
18
Chapter 1
Introduction
[TestMethod] public void TestCase2() { // another test case } [TestCleanup] public void After() { // run after each test case } [ClassCleanup] public static void AfterAll() { // run after all test cases, typically, close browser } Please note that [ClassCleanup] does not guarantee all tests from one test class have been executed before a new test class is initialized. What does this mean for your execution? If you run one test case or all test cases in a single test class, [ClassCleanup] is invoked, it will run as you expected. However, when you run several test classes in one go, when [ClassCleanup] is invoked, it is nondeterministic (which could lead to many opened browser windows). This is not good. Read this MSDN blog post for explanation: “ClassCleanup May Run Later Than You Think.”9
Alternative Framework: NUnit NUnit10, inspired by JUnit, is an open-source unit testing framework for Microsoft .NET. If you have used JUnit before, you will find similarities in NUnit. Compared to VSTest, NUnit is more flexible for executing tests http://blogs.msdn.com/b/ploeh/archive/2007/01/06/classcleanupmayrun laterthanyouthink.aspx 10 http://nunit.org/ 9
19
Chapter 1
Introduction
from the command line with JUnit style test reports (which can be easily integrated with CI Servers). However, you will need to spend some effort getting NUnit to work with Visual Studio.
Run Recipe Scripts Test scripts for all recipes can be downloaded from this book’s site. They are all in the ready-to-run state. We include the target web pages as well as the Selenium test scripts. There are two kinds of target web pages: local HTML files and web pages on a live site. Running the tests written for live sites requires an Internet connection.
Run Test(s) in VS Code The most convenient way to run one test case or a test suite is to do it in an IDE. When you have a large number of test cases, the most effective way to run all tests is done by a continuous testing process, which we cover in a later chapter.
Find the Test Case You can locate the recipe either by following the chapter or searching by name. There can be hundreds of test cases in one test project. Being able to quickly navigate to the test case is important when your test suite is large. Visual Studio Code has a Navigate To Symbol command; its default keyboard shortcut is Command + T on Mac (or Control + T on Windows). See Figure 1-13.
20
Chapter 1
Introduction
Figure 1-13. Visual Studio Code’s Navigate To Symbol search box A pop-up window lists all artifacts (test methods and classes) in the project for your selection. The search starts as soon as you type, as you can see in Figure 1-14.
Figure 1-14. Visual Studio Code’s Navigate To Symbol search box jumping to a specific test
Run an Individual Test Case Under the [TestMethod] annotation, there is an option called Run Test. Click this button to run the single test case (see Figure 1-15).
21
Chapter 1
Introduction
Figure 1-15. The Run Test button in Visual Studio Code Figure 1-16 shows a screenshot of the execution panel where one test case has passed.
Figure 1-16. Visual Studio Code execution panel after executing a test
Run All Test Cases in a Test Script File You can also run all test cases in the currently opened test script file by clicking the Run All Tests button under the [TestClass] annotation, as shown in Figure 1-17.
Figure 1-17. The Run All Tests (in the current file) button in Visual Studio Code
22
Chapter 1
Introduction
Figure 1-18 is a screenshot of the execution panel where all test cases in a test script file have passed.
Figure 1-18. Visual Studio Code execution panel after executing tests
Run Tests from the Command Line One key advantage of open-source test automation frameworks, such as Selenium, is FREEDOM. You can edit the test scripts in any text editor and run them from a command line. Here are two reasons why a test automation engineer must know how to execute tests from command line: •
You can eliminate issues from tools.
•
It’s required for continuous testing because the CT server invokes test executions this way.
To run a C# class, you need to compile it first (if you’re using an IDE, this is usually done automatically before execution). 1. Open a command prompt. You can use the standard command window (cmd. exe) or PowerShell. Also, most IDEs (including VS Code) provide an interface for the terminal. In VS code, you jump to the terminal with Control + `. 2. Change directory to your solution/working folder. cd C:\books\SeleniumRecipes-C#\recipes\ SeleniumRecipes
23
Chapter 1
Introduction
3. Run all test cases using the dotnet test in one test script (class). Run all tests in a file with dotnet test --filter NameSpace.TestClass. dotnet test --filter SeleniumRecipes. GoogleSearchDifferentBrowsersTest 4. Run an individual test case. To only run a single test case, use NameSpace. TestClass.TestMethod instead. For example: dotnet test --filter SeleniumRecipes. GoogleSearchDifferentBrowsersTest.TestInFirefox To run multiple test cases, use double quotations around the filter and the OR operator (|) to separate test classes: dotnet test --filter "SeleniumRecipes. GoogleSearchDifferentBrowsersTest.TestInFirefox | SeleniumRecipes.GoogleSearchDifferentBrowsersTest.TestInChrome" Sample output: Starting test execution, please wait... A total of 1 test files matched the specified pattern. Passed! - Failed: 0, Passed: 2, Skipped: 0, Total: 2, Duration: 12 s - SeleniumRecipesCSharp.dll (net7.0)
24
CHAPTER 2
Locating Web Elements As you may have already figured out, to drive an element in a page, you need to find it first. Selenium uses locators to find and match elements on web page. There are eight locators in Selenium, shown in Table 2-1.
Table 2-1. Selenium Locators Table
Example
ID
FindElement(By.Id("user"))
Name
FindElement(By.Name("username"))
Link Text
FindElement(By.LinkText("Login"))
Partial Link Text
FindElement(By.PartialLinkText("Next"))
Xpath
FindElement(By.Xpath("//div[@id='login']/ input"))
Tag Name
FindElement(By.TagName("body"))
Class Name
FindElement(By.ClassName("table"))
CSS
FindElement(By.CssSelector, "#login > input[type='text']"))
© Courtney Zhan, Edited by Zhimin Zhan 2024 C. Zhan, Selenium WebDriver Recipes in C#, https://doi.org/10.1007/979-8-8688-0023-8_2
25
Chapter 2
Locating Web Elements
Selenium WebDriver 4 (released in October 2021) added a new locator type called Relative, which we don’t find that useful, yet. We include one simple example use of one relative locator in this chapter and more in Chapter 25. You may use any one of the locators to narrow down the element you are looking for.
S tart a Browser Testing websites starts with a browser. static WebDriver driver = new ChromeDriver(); driver.Navigate().GoToUrl("https://agileway.com.au/demo") // or driver.Url = "https://agileway.com.au/demo"; Use ChromeDriver, SafariDriver, EdgeDriver, and FirefoxDriver for testing in Chrome, Safari, Edge, and Firefox, respectively.
Note: Test Site We prepared the test pages for the recipes. You can download them (in a zip file) from the book’s site. Unzip to a local directory and refer to test pages like this: siteUrl = "file:///Users/courtney/work/books/ SeleniumRecipes-C%23/site";driver.Navigate(). GoToUrl(siteUrl + "/button.html"); For beginners, we recommend closing the browser window at the end of a test class. driver.Quit(); 26
Chapter 2
Locating Web Elements
There is also driver.Close(), which closes the browser window with the focus. driver.Quit() closes all browser windows and ends the WebDriver session.
Inspect a Web Element in a Browser Note Every web page is set by its page source in HTML. A simple way to find the HTML fragment for a web element is to right-click the web element in a Chrome browser and select Inspect, as shown in Figure 2-1.
Figure 2-1. Inspect mode on the Chrome browser Then choose an appropriate Selenium locator based on the HTML fragment. It is not hard, and you don’t even have to know HTML well. After some trial and error (like the recipes in this book), you will get it quite quickly. For example, for the text box in Figure 2-1, name="comment" can be used to locate it.
27
Chapter 2
Locating Web Elements
Find an Element by ID Using an ID is the easiest and safest way to locate an element in HTML, if it exists. For a web page that is W3C HTML compliant1, the IDs should be unique and identified in web controls. In comparison to texts, test scripts that use IDs are less prone to application changes (e.g., developers may decide to change the label, but are less likely to change the ID). driver.FindElement(By.Id("submit_btn")).Click(); // Button driver.FindElement(By.Id("cancel_link")).Click(); // Link driver.FindElement(By.Id("username")).SendKeys("agileway"); // Textfield driver.FindElement(By.Id("alert_div")).getText(); // HTML Div element
Find an Element by Name The name attributes are used in form controls such as text fields and radio buttons. The values of the name attributes are passed to the server when a form is submitted. In terms of the least likelihood of a change, the name attribute is probably as good as an ID. driver.Navigate().GoToUrl(TestHelper.SiteUrl() + "/ locators.html"); driver.FindElement(By.Name("comment")). SendKeys("Selenium Cool");
https://zhiminzhan.medium.com/too-many-failed-javascript-testautomation-frameworks-fed006da05ec 1
28
Chapter 2
Locating Web Elements
Find an Element by Link Text For hyperlinks only, using a link’s text is probably the most direct way to click a link because it is what you see on the page. driver.FindElement(By.LinkText("Cancel")).Click();
Find an Element by Partial Link Text Selenium allows you to identify a hyperlink control with partial text. This can be quite useful when the text is dynamically generated. In other words, the text on one web page might be different on your next visit. You might be able to use the common text shared by these dynamically generated link texts to identify them. // will click the "Cancel" link driver.FindElement(By.PartialLinkText("ance")).Click();
Find an Element by XPath XPath, the XML Path Language, is a query language for selecting nodes from an XML document. When a browser renders a web page, it parses it into a DOM tree or similar. XPath can be used to refer to a certain node in the DOM tree. If this sounds a little too technical for you, don’t worry; just remember that XPath is the most powerful way to find a specific web control in HTML. // clicking the checkbox under 'div2' container driver.FindElement(By.XPath("//*[@id='div2']/input[@type= 'checkbox']")).Click(); Some testers feel intimidated by the complexity of XPath. However, in practice, there is only a limited scope of XPath to master for testers.
29
Chapter 2
Locating Web Elements
AVOID USING COPIED XPATH FROM A BROWSER’S DEVELOPER TOOL The browser’s developer tool (right-click to select the Inspect element to show it) is very useful for identifying a web element in a web page. You may get the XPath of a web element there, as shown in Figure 2-2 (in Chrome).
Figure 2-2. Copying the XPath of an element The copied XPath for the second Click here link in the example is as follows: //*[@id="container"]/div[3]/div[2]/a It works. However, we do not recommend this approach because the test script is fragile. If a developer later adds another div under , the copied XPath will no longer be correct for the element, while //div[contains(text(), "Second")]/ a[text()="Click here"] still works. In summary, XPath is a very powerful way to locate web elements when Id, Name, or LinkText are not applicable. Try to use an XPath expression that is less vulnerable to structure changes around the web element.
30
Chapter 2
Locating Web Elements
Find an Element by a Tag Name There are a limited set of tag names in HTML. In other words, many elements share the same tag names on a web page. You normally don’t use the tag_name locator by itself to locate an element. You often use it with others in chained locators (see the section below). However, there is an exception: driver.FindElement(By.TagName("body")).Text; The above test statement returns the text view of a web page. This is a very useful one because Selenium WebDriver does not have a built-in method to return the text of a web page.
Find an Element by Class The class attribute of an HTML element is used for styling. It can also be used for identifying elements. Commonly, an HTML element’s class attribute has multiple values, like so: Cancel Submit You may use any one of them. driver.FindElement(By.ClassName("btn-primary")).Click(); // Submit button driver.FindElement(By.ClassName("btn")). Click(); // Cancel link // the below will return error "Compound class names not permitted" // driver.FindElement((By.ClassName("btn btn-deault btn- primary")).Click();
31
Chapter 2
Locating Web Elements
The ClassName locator is convenient for testing JavaScript/CSS libraries (such as TinyMCE), which typically use a set of defined class names. // inline editing driver.FindElement(By.Id("client_notes")).Click(); System.Threading.Thread.Sleep(500); driver.FindElement(By.ClassName("editable-textarea")). SendKeys("inline notes"); System.Threading.Thread.Sleep(500); driver.FindElement(By.ClassName("editable-submit")).Click();
Find an Element by CSS Selector You may also use the CSS path to locate a web element. driver.FindElement(By.CssSelector("#div2 > input[type='checkbox']")).Click(); However, the use of a CSS selector is generally more prone to structure changes of a web page.
Find an Element by Relative Locators The purpose of relative locators is to find a specific element(s) regarding the position of another element. There was hype about relative locators (first introduced in Sahi Pro). However, we have reservations for two reasons:
32
•
We rarely have need for relative locators, so XPath is fine.
•
The proximity check (used in relative locators) does not always work as expected.
Chapter 2
Locating Web Elements
Here are quotes from Simon Stewart’s Selenium 4 master course on TestGuild2: •
“The way that proximity works, things are looking like they should be found, but sometimes aren’t.”
•
“Be aware that relative locators are very sensitive to page layout.”
Here is a simple example: using static OpenQA.Selenium.RelativeBy; IWebElement submitBtn = driver.FindElement(By. ClassName("btn")); IWebElement textField = driver.FindElement(RelativeBy. WithLocator(By.Name("comment")).Above(submitBtn)); You will find more examples of using this new relative locators in Chapter 25.
Chain FindElement to Find Child Elements For a page containing more than one element with the same attributes, like the following one, you can use the XPath locator.
Same checkbox in Div 1
Same checkbox in Div 2
https://testguild.com/course/relative-locators
2
33
Chapter 2
Locating Web Elements
There is another way: you can chain several FindElement instances to find a child element. driver.FindElement(By.Id("div2")).FindElement(By.Name("same")). Click();
Find Multiple Elements As its name suggests, FindElements returns a list of matched elements back. Its syntax is the same as FindElement, so you can use any of the eight locators. The following test statement will find two checkboxes under div#container and click the second one: ReadOnlyCollection checkbox_elems = driver. FindElements(By.XPath("//div[@id='container']//input [@type='checkbox']")); System.Console.WriteLine(checkbox_elems); // => 2 checkbox_elems[1].Click(); Sometimes FindElement fails due to multiple matching elements on a page, which you were not aware of. FindElements will come in handy to find them out.
L ocate a Web Element That Disappears After Inspect Dynamic elements are generated on the fly and often do not exist in the static page source. The only practical way (we are aware of ) is to get them by inspecting the dynamic element directly. However, some web elements disappear after you select the Inspect menu item (via right-click) because their focus has been lost.
34
Chapter 2
Locating Web Elements
There are two workarounds: 1. Open the developer tools in Chrome and select the Elements tab, right-click the parent node of the element you want to inspect, and in the contextual menu, click Break on ➤ Subtree modifications (Figure 2-3).
Figure 2-3. Chrome’s “Break on subtree modifications” setting 2. One simple workaround (more like a hack, but it works) is to type the following in the browser console: setTimeout(() => { debugger; }, 5000) This gives you 5 seconds to check the element source before the debugger shows up. See Figure 2-4.
35
Chapter 2
Locating Web Elements
Figure 2-4. Chrome’s browser debugger mode
36
CHAPTER 3
Hyperlink Hyperlinks (or links) are fundamental elements of web pages. As a matter of fact, hyperlinks make the World Wide Web possible. A sample link is shown in Figure 3-1 and then we show the HTML source.
Figure 3-1. An example of a hyperlink HTML source: Recommend Selenium
Click a Link by Text Using text is probably the most direct way to click a link in Selenium, as it is what we see on the page. driver.FindElement(By.LinkText("Recommend Selenium")).Click(); Please note that using CSS (e.g. text-transform: uppercase;) might change the text view from its HTML source. In this case, use the text as you see.
© Courtney Zhan, Edited by Zhimin Zhan 2024 C. Zhan, Selenium WebDriver Recipes in C#, https://doi.org/10.1007/979-8-8688-0023-8_3
37
Chapter 3
Hyperlink
Click a Link by ID driver.FindElement(By.Id("recommend_selenium_link")).Click(); Furthermore, if you are testing a web site with multiple languages, using IDs is probably the most favorable option. You do not want to write test scripts like the following: if (isItalian()) { driver.FindElement(By.LinkText("Accedi")).Click(); } else if (isChinese()) { // a helper function determines the locale driver.FindElement(By.LinkText, "登录").Click(); } else { driver.FindElement(By.LinkText("Sign in")).Click(); }
Click a Link by Partial Text driver.FindElement(By.PartialLinkText("Recommend Seleni")). Click();
Click a Link by XPath This example finds a link with the text “Recommend Selenium” under a
tag: driver.FindElement(By.XPath("//p/a[text()='Recommend Selenium']")).Click();
38
Chapter 3
Hyperlink
You might say the example before (find by LinkText) is simpler and more intuitive. That’s correct, but let’s examine another example, shown in Figure 3-2.
Figure 3-2. An example of hyperlinks On this page, there are two Click here links. HTML source: First div Click here Second div Click here If the test requires you to click the second Click here link, the simple FindElement(By.LinkText("Click here")) won’t work (because it clicks the first one). Here is a way to accomplish this using XPath: driver.FindElement(By.XPath( "//div[contains(text(), \"Second\")]/a[text()=\"Click here\"]")).Click();
39
Chapter 3
Hyperlink
Click the Nth Link with Exact Same Label It is not uncommon that there are multiple links with exactly the same text. By default, Selenium will choose the first one. What if you want to click the second or Nth one? The web page shown in Figure 3-3 contains three Show Answer links.
Figure 3-3. Three ‘Show Answer’ links with the same label To click the second one, Assert.IsTrue(driver.FindElements(By.LinkText("Show Answer")). Count == 2); ReadOnlyCollection links = driver.FindElements(By. LinkText("Show Answer")); links[1].Click(); // click the second one Assert.IsTrue(driver.PageSource.Contains("second link page")); // second link FindElements return a collection (also called an array by some) of web controls matching the criteria in the appearing order. Selenium (in fact, C#) uses 0-based indexing (i.e., the first one is 0).
Click the Nth Link by CSS Selector You may also use CSS selector to locate a web element. // Click the 3rd link directly in
tag driver.FindElement(By.CssSelector("p > a:nth-child(3)")).Click();
40
Chapter 3
Hyperlink
However, generally speaking, the use of a stylesheet is more prone to changes.
Verify If a Link Is Present or Not Assert.IsTrue(driver.FindElement(By.LinkText("Recommend Selenium")).Displayed); Assert.IsTrue(driver.FindElement(By.Id("recommend_selenium_ link")).Displayed);
Get Link Data Attributes Once a web control is identified, you can get other attributes of the element. This is generally applicable to most of the controls. It’s typically used for assertion purposes. Assert.AreEqual(TestHelper.SiteUrl() + "/index.html", driver.FindElement(By.LinkText("Recommend Selenium")). GetAttribute("href") ); Assert.AreEqual("recommend_selenium_link", driver.FindElement(By.LinkText("Recommend Selenium")). GetAttribute("id")); Assert.AreEqual("Recommend Selenium", driver.FindElement(By.Id("recommend_selenium_link")).Text); Assert.AreEqual("a", driver.FindElement(By.Id("recommend_selenium_link")).TagName); Also, you can get the value of custom attributes of this element and its inline CSS style.
41
Chapter 3
Hyperlink
Assert.AreEqual("font-size: 14px;", driver.FindElement(By.Id("recommend_selenium_link")). GetAttribute("style")); // Please note using attribute_value("style") won't work Assert.AreEqual("123", driver.FindElement(By.Id("recommend_selenium_link")). GetAttribute("data-id"));
Test If a Link Opens a New Browser Window Clicking the following link will open the linked URL in a new browser window or tab: Open new window While you could use the SwitchTo() method (see Chapter 10) to find the new browser window, it’s easier to perform all testing within one browser window. Here’s how: String currentUrl = driver.Url; String newWindowUrl = driver.FindElement(By.LinkText("Open new window")). GetAttribute("href"); driver.Navigate().GoToUrl(newWindowUrl); driver.FindElement(By.Name("name")).SendKeys("sometext"); driver.Navigate().GoToUrl(currentUrl); // back In this test script, you use a local variable named currentUrl to store the current URL.
42
CHAPTER 4
Button Buttons can come in two forms: standard and submit buttons. Standard buttons are usually created by the button tag, whereas submit buttons are created by the input tag (normally within forms). See Figure 4-1.
Figure 4-1. Button examples HTML source: Choose Selenium
Yes No/option>
The intention of the following test script is to select Yes in the dropdown list, but it is not aware that there is another checkbox control sharing the same name attribute: Selenium::WebDriver::Support::Select.new(driver.FindElement(By. Name("vip"))).SelectByText("Yes") Here is the error returned: 'ArgumentError: unexpected tag name "input"' The solution is quite obvious after knowing the cause: change the locators, such as FindElement. A quite common scenario is as follows, where a hidden element and a checkbox element share the same ID and NAME attributes: