Open kazurayam opened 1 year ago
At first, I needed to identify which test classes wrote which files in the project's root directory.
I had to read the source codes in the selenium-webdriver-junit4
subproject .
Created file
2023.10.24_22.07.27.742-7440524241d0dbd63ca5eec377b6455c.png
2023.10.24_22.07.29.333-7440524241d0dbd63ca5eec377b6455c.png
extentReport.html
fullpage-screenshot-chrome.png
fullpage-screenshot-firefox.png
6. login.har
my-pdf.pdf - https://github.com/kazurayam/selenium-webdriver-java/blob/master/selenium-webdriver-junit4/src/test/java/io/github/bonigarcia/webdriver/junit4/ch05/print/PrintChromeJUnit4Test.java - https://github.com/kazurayam/selenium-webdriver-java/blob/master/selenium-webdriver-junit4/src/test/java/io/github/bonigarcia/webdriver/junit4/ch05/print/PrintEdgeJUnit4Test.java - https://github.com/kazurayam/selenium-webdriver-java/blob/master/selenium-webdriver-junit4/src/test/java/io/github/bonigarcia/webdriver/junit4/ch05/print/PrintFirefoxJUnit4Test.java
screenshot.png
testAccessibility.json
webdrivermanager.pdf
webdrivermanager.png
webelement-screenshot.png
The other subprojects (-junit4seljp
, -junit5
, -testng
) also have the ducplicating source codes.
In which directory under the project root should I house the output files from tests?
As for Maven, https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html writes
The target directory is used to house all output of the build.
As for Gradle, https://docs.gradle.org/current/userguide/directory_layout.html#dir:project_root writes
The build directory of this project into which Gradle generates all build artifacts.
My question: target
directory or build
directory, which directory to choose?
... Neither. I do not want any test case source dependent on which build tool to be used.
I looked at https://github.com/kazurayam/selenium-webdriver-java/blob/master/.gitignore
It contains a line
test-output
I believe that @bonigarcia had an intention to create the test-output
directory.
However, the current test classes are written so that they write the files into the project's root directory, rather than the test-output
directory.
Then, I would modify the test class so that they write files into the test-output
directory.
How should I change the existing sources so that they write files into the new test-output
directory?
At first I should study the existing code. For example, https://github.com/kazurayam/selenium-webdriver-java/blob/master/selenium-webdriver-junit4/src/test/java/io/github/bonigarcia/webdriver/junit4/ch04/event_listeners/MyEventListener.java has the following fragment, which decides the path to write the file into
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy.MM.dd_HH.mm.ss.SSS");
String screenshotFileName = String.format("%s-%s.png",
dateFormat.format(today), sessionId.toString());
Path destination = Paths.get(screenshotFileName);
I want the change to be minimum and clean:
So, how about adding a helper class: com.kazurayam.unittest.TestHelper
. Provided that I have it, I would modify the above code as follows:
import com.kazurayam.unittest.TestHelper;
...
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy.MM.dd_HH.mm.ss.SSS");
String screenshotFileName = String.format("%s-%s.png",
dateFormat.format(today), sessionId.toString());
Path destination = TestHelper.resolveOutput(screenshotFileName);
The package name is arguable. The candidates include:
io.github.bonigarcia.webdriver.TestHelper
com.kazurayam.unittest.TestHelper
Well, I must not pretend to be @bonigarcia myself. So I would call my class as com.kazurayam
something.
In the selenium-webdriver-junit5
subproject, I executed
$ mvn test
that is, I executed full set of tests by Maven build. The result was as follows:
Just similar set of output files were created in the project root dir as the selenium-webdriver-junit4
subproject. I expected this. Fine.
I would create several branches: kazurayam8a, kazurayam8b, etc. In each branches, I would work modifying the source code. In each branch, I would work for a single output file to be moved into the test-output
directory. In each brach, I would modify the codes of 4 subprojects -junit4
, -junit5
, -junit5seljup
and -testng
The plan is as follows:
branch | output file | code to change |
---|---|---|
kazurayam8a | add com.kazurayam.unittest.TestHelper class | https://github.com/kazurayam/unittest-helper |
kazurayam8b inherits kazurayam8a | 2023.10.24_22.07.27.742-7440524241d0dbd63ca5eec377b6455c.png and 2023.10.24_22.07.29.333-7440524241d0dbd63ca5eec377b6455c.png | junit4/ch04/event_listeners/ |
kazurayam8c | extentReport.html | junit4/ch09/reporting |
kazurayam8d | fullpage-screenshot-chrome.png | junit4/ch05/cdp/FullPageScreenshotChrome... and Firefox etc |
kazurayam8e | login.har | junit4/ch09/performance |
kazurayam8f | my-pdf.pdf | junit4/ch05/print and Firefox etc |
kazurayam8g | screenshot.png | junit4/ch04/screenshots/ |
kazurayam8g | webelement-screenshot.png | junit4/ch04/screenshots/ |
kazurayam8h | testAccessibility.json | junit4/ch09/accessibility/ |
kazurayam8i | webdrivermanager.pdf and webdrivermanager.png | junit4/ch09/download/ |
I need to be careful about the "Current Working Directory". Now I have a statement in my test class source:
Path static testOutputDir = Paths.get("test-output");
This assumes that the "Current Working Directory" is given with a value equal to the directory selenium-webdriver-java/selenium-webdriver-junit4
.
However, this assumption is too fragile according to the runtime environment. In https://discuss.gradle.org/t/how-do-i-set-the-working-directory-for-testng-in-a-multi-project-gradle-build/7379/7,
luke_daley Gradle Employee Nov '13 Loading from the filesystem using relative paths during unit tests is problematic because different environments will set a different working directory for the test process. For example, Gradle uses the projects directory while IntelliJ uses the directory of the root project. The only really safe way to solve this problem is to load via the classpath.
A case
:~/github/selenium-webdriver-java (kazurayam8a *+)
$ gradle :selenium-webdriver-junit4:test -q --tests com.kazurayam.unittest.TestHelper
This command passed and it created a directory selenium-webdriver-java/selenium-webdriver-junit4/test-output
. This is what I expected. Fine. Very Good.
However, in IntelliJ IDEA, in the Java editor, I opend the com.kazurayam.unittest.TestHelper
source, and right-click to choose "Run TestHelper.test_resolveOutput()"
It ran passed, but it created a directory selenium-webdriver-java/test-output
. This is NOT what I expected.
IntelliJ run the test with "Current Working Directory" = selenium-webdriver-java
, not = selenium-webdriver-java/selenium-webdirver-junit4
.
This IntelliJ's behavior confuses me.
I should find out how to configure IntelliJ IDEA so that it works just like Gradle. However, is it possible? ---- I am not sure.
I have developed a new class test/java/com.kazurayam.unittest.TestHelper
with a method Path resolveOutput(String fileName)
.
I will commit this in the kazurayam8a branch.
A call to TestHelper.resolveOutput("extentReport.html")
will return a Path selenium-webdriver-java/selenium-webdriver-junit4/test-output/extentReport.html
. This is good.
The TestHelper.resolveOutput("foo")
will NOT return a Path selenium-webdriver-java/test-output/foo
. Rather it will return selenium-webdriver-java/selenium-webdriver-junit4/test-outpu/foo
. This subtle difference matters.
As you see in
kazurayam developed a package of classes: com.kazurayam.unittest.TestHelper
, ProjectDirectoryResolver
and StringSequence
. This package resolves this #8 issue.
However there is a problem. The package com.kazurayam.unittest
is contained in the selenium-webdriver-java/selenium-webdriver-junit4
project. On the other hand, the other projects *-junit5
, *-junit5seljup
and *-testng
will also require this package.
I do not like to duplicate the source code of the com.kazurayam.unittest
package. Therefore I will move this package into a new independent project. The project name will be unittest-helper-x.x.x.jar
.
I will publish the jar of unittesthelper-x.x.x.jar
to the Maven Central repository. Therefore the jar will be available to any Gradle build.gradle and Maven pom.xml.
I have created a project "com.kazrurayam:unittest-helper:0.1.0"
https://github.com/kazurayam/unittest-helper
I have published the jar to the Maven Central repository, which will become available for download in a few days.
I will modify the branches kazurayam8, kazurayam8a, kazurayam8b, kazurayam8c, kazurayam8d so that the use the "com.kazrurayam:unittest-helper:0.1.0" as one of their dependencies downloaded from the maven repositories.
https://github.com/kazurayam/selenium-webdriver-java/issues/21
I found that the sample codes of the Chapter 9 "File Download" section are sensitive. There are 3 tests which write into output files.
One writes a file into the "Downloads" dir under the System.getProperty("user.home")
= OS User Directory.
One writes a file into the dir as new File(".")
One writes a file into the file as new File("", fileName)
It seems that the book author, @bonigarcia, had a specific intention to show the ways how to locate the output files, but I am not sure.
We would need a sample code that writes a file into the "Downloads" directory of a user.
Should I modify the samples that uses new File(".")
? ------- I wondered a while ----- Yes, I would propose to do so.
All the works required for the issue #8 have been done. The tag issue8_done
was created.
https://github.com/kazurayam/selenium-webdriver-java/tree/issue8_done
See the project's file tree:
All files generated by the tests are written into a single directory test-output
under the project's root directory. The test-output
directory is gitignored.
This file tree looks clean to me. I like this.
I have got an additional requirement. I want to create subdirectory under the output dir.
The subdirectory could be any string. For example, I can set the Fully Qualified Class Name of the test case class as the subDir. Once implemented then the paths of output would look like this:
selenium-webdriver-java/selenium-webdriver-junit4/test-output/io.github.bonigarcia.webdriver.junit4.event_listener.MyEventListener/2023.10.24_22.07.27.742-7440524241d0dbd63ca5eec377b6455c.png
selenium-webdriver-java/selenium-webdriver-junit4/test-output/io.github.bonigarcia.webdriver.junit4.event_listener.MyEventListener/2023.10.24_22.07.29.333-7440524241d0dbd63ca5eec377b6455c.png
The path becomes rich. The path tells us which test class created the file.
With the unittest-helper-0.2.0.jar
, I have managed to make the following test-output
. Please note that
all output files created by test class are written into a single dedicated directory test-output
. No file is written in the project's root directory
Under the test-output
directory, we have a layer of directories which represents the Fully Qualified Class Name of the test classes.
I think that this file organization is nice.
The unittest-helper project published a new version v0.3.0
https://github.com/kazurayam/unittest-helper/releases/tag/0.3.0
The API has been changed. The selenium-webdriver-java project should use the unittest-helper v0.3.0.
I will update the kazurayam8consolidated branch.
The following graph shows the tree of a project root directory which contains multiple subprojects:
Then I executed all tests of the subprojects.
When all tests finished, I viewed the directory tree under a subproject
selenium-webdriver-junit4
I found a lot of new files under the subproject's root directory. I executed
git status
command to find the new files:These new files are not
gitignored
. Therefore if I carelessly do the following operation:then the newl files will be commited into the project tree. A disastrous plution of the project tree!
The sample tests in the book should not write files into the project's root directory. The tests should write files into a particular directory in the project's root directory.
And I want to list the directroy in the
.gitignore
file so that Git ignores all the test outputs silently.