$30
For this assignment, you will write a systems-level, automated
black-box tests for the Reddit website using the Selenium IDE. Specifically,
## Task 1: Write test cases
Write a test case for each requirement listed in
[requirements.md](requirements.md). Name each test case same as the
requirement name (e.g. FUN-TITLE). I'm asking you to do this for the purposes
of GradeScope autograding. Normally, you would use a more descriptive name.
Remember, each test must end with an assertion! The list of available
assertions and other commands are available at:
https://www.selenium.dev/selenium-ide/docs/en/api/commands
### Tips for Writing assertions for each Test
You will want to use the below commands and assertions to test each of the requirements:
FUN-TITLE: "assert title"
FUN-JOIN-BUTTON-EXISTS - "assert text"
FUN-SIGNUP-LINK - "store attribute" followed by "assert". You will be storing
the attribute value to a Selenium variable and asserting on the value of that
variable. Now there is a defect in Selenium IDE with the "store attribute"
command where the target selector button is disabled when it should be enabled.
A work around is to enter a command such as "assert text" or "click" which
allows you to use the target selector, fill in the locator string using it, and
then revert to "store attribute". As I said, while Selenium web driver is very
mature, Selenium IDE is a work in progress. :)
FUN-SEARCH-SMELLY-CAT - "assert text"
FUN-RULE-3 - "assert text"
FUN-RULES-11-ITEMS - "assert element present" for the 11th item; "assert element not present" for the locator for the 12th item.
**Hint:** If you are really stuck, there is a solution project file [Reddit
Cats Solution.side](Reddit%20Cats%20Solution.side) that you can open from
Selenium IDE. Take a peek but don't loiter!
### Other Tips
Sometimes your test case will not work as expected. Here are a few hints on how to debug a problem:
1. Check the Log window at the bottom of the Selenium IDE. It will tell you
which step failed for what reason (in red).
1. Select the test step that failed in the main test case window, and then
select the Reference tab at the bottom pane of the IDE. It will display
usage instructions for that command. Remember always, the first argument goes
to the Target field and the second argument goes to the Value field, regardless
of command.
1. Sometimes the target component of a test step is the problem. The selector
button tries to generate a locator string as best it can using xpath, css
selector, or id tag. But it is not fool proof. The problem is, the web page
may change ever so slightly on the next page load (e.g. due to a new post, or a
new comment) and then the locator will stop working. You will notice that
there is a small down arrow at the end of the target text box. If you click on
that arrow, you will see alternative locator strings to the current string.
Select the one that looks specific enough to be able to point to the target but
also general enough to not change between page loads. You do need to try this
out several times to get a feel of what a good locator string is. Here is an
in-depth discussion about locators:
https://www.selenium.dev/documentation/en/getting_started_with_webdriver/locating_elements/#element-selection-strategies
1. Sometimes you can use an XPATH position locator string to check that an
element exists at an expected location ("assert element present") or does
not exist ("assert element not present"). But to do this, you have to select
the XPath position locator string in the drop-down list of optional strings in
the Target field.
1. For those of you who are working in groups, you will be working on the same
shared .side project file. So it is especially important that your pull
before opening the project file and push immediately after you have modified
and saved the project file. Otherwise, you may get merge conflicts. Merging
conflicts is possible by using the technique I went over with the
[Using\_Git](https://github.com/wonsunahn/CS1632_Fall2020/blob/master/lectures/Using_Git.pdf)
slides, but it's best to avoid it.
## Task 2: Add test cases to test suite and save project
1. Choose "Test Suites" from the left panel drop down menu.
1. There will already be a "Default Suite" there with possibly one or more tests.
1. Right click on "Default Suite", or click on the vertical-3-dot context menu button, and select "Rename" and rename to "RedditCats".
1. Right click on "RedditCats", or click on the vertical-3-dot context menu
button, and select "Add tests". Make sure all tests are checked as shown in
the below figure. Press on the "Select" button.
<img alt="Test Suite" src=test-suite-selection.png width=700
1. Click on the "Save project" button on the top right corner that looks like a
floppy disk. Save to file name "Reddit Cats.side" in the exercise root folder.
## Task 3: Export test suite to JUnit class
Once you are done writing your Selenium test suite, let's try exporting the test
suite in Selenium IDE to a Java JUnit test class.
Follow these instructions:
1. Right click on "RedditCats", or click on the vertical-3-dot context menu
button, and select "Export".
1. Select "Java JUnit" in the list of language options and optionally check
"Include step descriptions as a separate comment" to generate more detailed
comments. Leave other boxes unchecked.
1. Save the resulting file into "RedditCatsTest.java".
You can now run the RedditCatsTest JUnit class using the provided
[TestRunner.java](TestRunner.java) using one of the following scripts:
* If you are running Windows:
```
cd Windows
run.bat
```
* If you are running Mac:
```
cd Mac
run.sh
```
* If you are running Linux:
```
cd Linux
run.sh
```
Note that the script only works if you have Chrome version 85 installed on your
computer (the most recent version as of today). If you have a different
version of Chrome, you may have to update the chromedriver.exe (or
chromedriver) in your respective OS folder (Windows / Mac / Linux) by
downloading a new Chrome Web Driver from:
https://chromedriver.chromium.org/downloads
Your Chrome version can be obtained by clicking on the vertical-3-dot menu at
the top right corner of your browser, then Help About Google Chrome.
If things go properly, you will see the Chrome browser pop up repeatedly for
each test case, perform the actions, and close. In the command line, you
should see "ALL TESTS PASSED", which is printed by TestRunner if there are no
failures.
There are multiple reasons why you would want to export to JUnit:
1. You may have a pre-existing testing framework in JUnit (or Python Pytest, or
JavaScript Mocha, etc). And you may want to merge the Selenium IDE testing
script to the language and framework of your choice.
1. Exporting to JUnit really gives you a good sense of what's happening under
the covers (in terms of the actual calls to the WebDriver). Also, if there
is a test case that is particularly hard to nail down just by using Selenium
IDE, you can touch it up in the form of exported Java code.
1. Selenium IDE also gives the option to export your JUnit test directly to a
Selenium Grid which can run the test cases in parallel. This can allow you
to utilize a server farm to finish your testing very quickly, although we will
not explore this option today.
### Tips for JUnit + Selenium problem solving
1. Often problems that are not apparent in the Selenium IDE commands become apparent in the Java code. Read the Java code to detect problems.
1. If you want to run your Selenium tests on Eclipse using the "Run JUnit" feature, you will have to also add this line to the beginning of the @Before setUp() method:
```
System.setProperty("webdriver.chrome.driver", "Windows/chromedriver.exe");
```
Or whatever the path is to your OS compatible chromedriver.
1. One common problem with Selenium is that it takes a long time for certain web pages or web elements to load and if Selenium proceeds with testing immediately after opening a page, the tests will fail. So Selenium provides APIs to allow you to wait until an event happens (e.g. the element is loaded). All the details about which APIs to use on which situations is in the page:
https://www.selenium.dev/documentation/en/webdriver/waits/
For your purposes, an implicit wait setting at the beginning should be enough. Insert the following line in the @Before setUp() method:
```
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
```
In order to use that line, you will need to also import this library:
```
import java.util.concurrent.TimeUnit;
```
What that does is: for every step, if the corresponding element is missing, it inserts an implicit wait of 10 seconds before signaling a failure.
1. Another common problem is that depending on the browser window size, certain elements may disappear. For example, the Reddit site would hide the "rules" bar on the right hand side if the windows is too narrow. One way to solve this is to uniformly set the window size at the setUp() method so that all your tests will have the correct size:
```
driver.manage().window().setSize(new Dimension(1200, 800));
```
And remove all calls to setSize in your test cases.
You'd be surprised! Make sure you are accessing the former and not the latter.