Skip to content

Commit

Permalink
Manage settings internally without exposing them as system properties
Browse files Browse the repository at this point in the history
  • Loading branch information
bjuric committed Oct 24, 2024
1 parent 36f0893 commit ce05d10
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 74 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
4.0.0
=====
15 October 2024
24 October 2024
- Introduce Gwen processes to support multiple launch configurations
- `-p|--process` option
- Require Java 17+ instead of Java 11+
- Use logback instead of log4j for logging
- Support `empty` literal in DSLs wherever `blank` is accepted
- Replace internal stack of data caches with a single data cache (internal enhancement)
- Internal engine enhancements
- Replace internal stack of data caches with a single data cache
- Manage settings internally without exposing them as system properties
- Add implicit variable(s):
- `gwen.process.name`
- Add environment variable(s)
Expand Down
10 changes: 5 additions & 5 deletions src/main/scala/gwen/web/GwenWebInterpreter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ package gwen.web

import gwen.GwenInterpreter
import gwen.core.Settings
import gwen.core.GwenOptions
import gwen.core.GwenSettings

import gwen.web.init.WebProjectInitialiser
import gwen.web.eval.WebBrowser
import gwen.web.eval.WebEngine
import gwen.web.eval.WebSettings
import gwen.core.GwenOptions

import java.io.File

Expand All @@ -44,12 +45,11 @@ object GwenWebInterpreter extends GwenInterpreter(new WebEngine()) with WebProje

override def init(options: GwenOptions): GwenOptions = {
val opts = if (!options.init) {
val conf = Some(Settings.BootstrapConf)
val baseDir = Settings.get("gwen.baseDir", None, conf)
val baseDir = GwenSettings.`gwen.baseDir`
val browserConf = {
val browsersDir = new File(new File(baseDir, "conf"), "browsers")
if (browsersDir.exists && WebBrowser.findSettingsFile(options.settingsFiles).isEmpty) {
val targetBrowser = Settings.get(`gwen.target.browser`, None, conf)
val targetBrowser = Settings.get(`gwen.target.browser`)
List("conf", "json", "properties") map { confType =>
new File(browsersDir, s"$targetBrowser.$confType")
} find { conf =>
Expand All @@ -60,7 +60,7 @@ object GwenWebInterpreter extends GwenInterpreter(new WebEngine()) with WebProje
val envConf = {
val envDir = new File(new File(baseDir, "conf"), "env")
if (envDir.exists && options.settingsFiles.filter(_.getPath.startsWith(s"$baseDir${File.separatorChar}env${File.separatorChar}")).isEmpty) {
val targetEnv = Settings.get(`gwen.target.env`, None, conf)
val targetEnv = Settings.get(`gwen.target.env`)
List("conf", "json", "properties") map { confType =>
new File(envDir, s"$targetEnv.$confType")
} find { conf =>
Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/gwen/web/eval/WebSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ object WebSettings extends LazyLogging {
*/
def `gwen.web.capture.screenshots.enabled`: Boolean = {
Settings.getBoolean("gwen.web.capture.screenshots.enabled", Some("gwen.web.capture.screenshots")) tap { isSet =>
if (isSet) Settings.set("gwen.report.slideshow.create", true.toString)
if (isSet) sys.props += (("gwen.report.slideshow.create", true.toString))
}
}

Expand All @@ -233,7 +233,7 @@ object WebSettings extends LazyLogging {
*/
def `gwen.web.capture.screenshots.highlighting`: Boolean = {
Settings.getBoolean("gwen.web.capture.screenshots.highlighting") tap { isSet =>
if (isSet) Settings.set("gwen.report.slideshow.create", true.toString)
if (isSet) sys.props += (("gwen.report.slideshow.create", true.toString))
}
}

Expand Down
21 changes: 0 additions & 21 deletions src/test/resources/sample/settings/sample.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,11 @@
{
"rp": {
"endpoint": "http://<host>:<port>",
"uuid": "28b262e7-8a9d-4928-b2a3-649562d5c63d",
"project": "default_personal",
"launch": "Gwen"
},
"gwen": {
"behavior": {
"rules": "strict"
},
"report": {
"overwrite": false
},
"rp": {
"heartbeat": {
"timeoutSecs": 5
},
"send": {
"failed": {
"errorBlocks": "leaf",
"stepDefs": "none"
},
"stepDefs": "inlined"
},
"testCaseId": {
"keys": "auto"
}
},
"web": {
"sendKeys": {
"clearFirst": false,
Expand Down
13 changes: 0 additions & 13 deletions src/test/resources/sample/settings/sample.properties
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
# RP client settings
rp.endpoint = http://localhost:8080
rp.uuid = 28b262e7-8a9d-4928-b2a3-649562d5c63d
rp.project = default_personal
rp.launch = Gwen

# Gwen core settings
gwen.behavior.rules = strict
gwen.report.overwrite = false

# Gwen RP settings
gwen.rp.heartbeat.timeoutSecs = 5
gwen.rp.send.failed.errorBlocks = leaf
gwen.rp.send.failed.stepDefs = none
gwen.rp.send.stepDefs = inlined
gwen.rp.testCaseId.keys = auto

# Chrome settings
gwen.web.chrome.args.0000000000 = --ignore-certificate-errors
gwen.web.chrome.args.0000000001 = --window-size=1920,1080
Expand Down
7 changes: 4 additions & 3 deletions src/test/scala/gwen/web/BaseTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ abstract class BaseTest extends AnyFlatSpec {
Settings.exclusively {
val original = Settings.getOpt(name)
try {
Settings.set(name, value)
sys.props += ((name, value))
Settings.init()
body
} finally {
original.fold(Settings.clear(name)) { v =>
Settings.set(name, v)
original.fold(sys.props -= name) { v =>
sys.props += ((name, v))
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/scala/gwen/web/eval/WebElementLocatorTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import org.scalatest.matchers.should.Matchers
class WebElementLocatorTest extends BaseTest with Matchers with MockitoSugar with BeforeAndAfterEach {

// disable implicit js locators for unit test
Settings.set("gwen.web.implicit.js.locators", "false")
sys.props += (("gwen.web.implicit.js.locators", "false"))

private var mockWebElement: WebElement = uninitialized
private var mockWebElements: List[WebElement] = uninitialized
Expand Down
14 changes: 8 additions & 6 deletions src/test/scala/gwen/web/eval/WebEngineTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1000,17 +1000,19 @@ class WebEngineTest extends BaseTest with Matchers with MockitoSugar with Before

"""<attribute> <is|will> be defined by property "<name>"""" should "evaluate" in {
List("is", "will be").zipWithIndex.foreach { case (x, i) =>
Settings.set(s"name-$i", s"$i")
evaluate(s"""attribute-$i $x defined by property "name-$i"""")
verify(mockTopScope).set(s"attribute-$i", s"$i")
withSetting(s"name-$i", s"$i") {
evaluate(s"""attribute-$i $x defined by property "name-$i"""")
verify(mockTopScope).set(s"attribute-$i", s"$i")
}
}
}

"""<attribute> <is|will> be defined by setting "<name>"""" should "evaluate" in {
List("is", "will be").zipWithIndex.foreach { case (x, i) =>
Settings.set(s"name-$i", s"$i")
evaluate(s"""attribute-$i $x defined by setting "name-$i"""")
verify(mockTopScope).set(s"attribute-$i", s"$i")
withSetting(s"name-$i", s"$i") {
evaluate(s"""attribute-$i $x defined by setting "name-$i"""")
verify(mockTopScope).set(s"attribute-$i", s"$i")
}
}
}

Expand Down
51 changes: 31 additions & 20 deletions src/test/scala/gwen/web/eval/WebSettingsTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import gwen.web._
import gwen.core.AssertionMode
import gwen.core.GwenOptions
import gwen.core.GwenSettings
import gwen.core.BootstrapSettings
import gwen.core.Settings
import gwen.core.behavior.BehaviorMode
import gwen.core.behavior.FeatureMode
Expand Down Expand Up @@ -76,6 +75,7 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
GwenSettings.`gwen.dryRun.limit.tableData.outline.examples.records` should be (Integer.MAX_VALUE)
GwenSettings.`gwen.error.messages.inline.locators` should be (false)
GwenSettings.`gwen.logLevel.deprecations` should be (Level.SEVERE)
GwenSettings.`gwen.launch.options.format` should be (List(ReportFormat.html, ReportFormat.results))
}
}

Expand Down Expand Up @@ -126,9 +126,17 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
Settings.exclusively {
withSetting("gwen.initDir", ".") {
Settings.init(
new File("src/main/resources/init/gwen.conf"),
new File("src/main/resources/init/conf/browsers/chrome.conf"))
assertInitConf(".", "target")
List(
new File("src/main/resources/init/gwen.conf"),
new File("src/main/resources/init/conf/browsers/chrome.conf")
)
)
assertInitConf()
GwenSettings.`gwen.auto.discover.data.csv` should be (false)
GwenSettings.`gwen.behavior.rules` should be (BehaviorMode.strict)
GwenSettings.`gwen.feature.mode` should be (FeatureMode.declarative)
GwenSettings.`gwen.baseDir`.getPath should be (".")
GwenSettings.`gwen.outDir`.getPath should be ("output")
}
}
}
Expand All @@ -137,31 +145,34 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
Settings.exclusively {
withSetting("gwen.initDir", "gwen") {
Settings.init(
new File("src/main/resources/init/gwen.conf"),
new File("src/main/resources/init/conf/browsers/chrome.conf"))
assertInitConf("gwen", "target")
List(
new File("src/main/resources/init/gwen.conf"),
new File("src/main/resources/init/conf/browsers/chrome.conf")
)
)
assertInitConf()
GwenSettings.`gwen.auto.discover.data.csv` should be (false)
GwenSettings.`gwen.behavior.rules` should be (BehaviorMode.strict)
GwenSettings.`gwen.feature.mode` should be (FeatureMode.declarative)
GwenSettings.`gwen.baseDir`.getPath should be ("gwen")
GwenSettings.`gwen.outDir`.getPath should be ("gwen/output")
}
}
}

private def assertInitConf(expectedBaseDir: String, expectedOutDir: String): Unit = {
private def assertInitConf(): Unit = {

GwenSettings.`gwen.assertion.mode` should be (AssertionMode.hard)
GwenSettings.`gwen.associative.meta` should be (true)
GwenSettings.`gwen.auto.bind.tableData.outline.examples` should be (true)
GwenSettings.`gwen.auto.discover.data.csv` should be (true)
GwenSettings.`gwen.auto.discover.data.json` should be (false)
GwenSettings.`gwen.auto.discover.meta` should be (true)
GwenSettings.`gwen.auto.trim.data.csv` should be (false)
GwenSettings.`gwen.auto.trim.data.json` should be (false)
GwenSettings.`gwen.behavior.rules` should be (BehaviorMode.lenient)
GwenSettings.`gwen.feature.dialect` should be ("en")
GwenSettings.`gwen.feature.failfast.enabled` should be (true)
GwenSettings.`gwen.feature.failfast.exit` should be (false)
GwenSettings.`gwen.feature.mode` should be (FeatureMode.imperative)
GwenSettings.`gwen.mask.char` should be ('*')
GwenSettings.`gwen.baseDir`.getPath should be (expectedBaseDir)
GwenSettings.`gwen.outDir`.getPath should be (expectedOutDir)
GwenSettings.`gwen.parallel.maxThreads` should be (GwenSettings.availableProcessors)
GwenSettings.`gwen.rampup.interval.seconds` should be (None)
GwenSettings.`gwen.report.overwrite` should be (false)
Expand All @@ -178,7 +189,7 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
GwenSettings.`gwen.console.repl.tabCompletion` should be (true)
GwenSettings.`gwen.logLevel.deprecations` should be (Level.SEVERE)

BootstrapSettings.`gwen.launch.options.format` should be (List(ReportFormat.html, ReportFormat.results))
GwenSettings.`gwen.launch.options.format` should be (List(ReportFormat.html))

WebSettings.`gwen.target.browser` should be (WebBrowser.chrome)
WebSettings.`gwen.target.env` should be ("test")
Expand Down Expand Up @@ -223,21 +234,21 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {

"Sample migration .conf" should "should override defaults" in {
Settings.exclusively {
Settings.init(new File("src/test/resources/sample/settings/sample.conf"))
Settings.init(List(new File("src/test/resources/sample/settings/sample.conf")))
assertMigrationSample()
}
}

"Sample migration .json" should "should override defaults" in {
Settings.exclusively {
Settings.init(new File("src/test/resources/sample/settings/sample.json"))
Settings.init(List(new File("src/test/resources/sample/settings/sample.json")))
assertMigrationSample()
}
}

"Sample migration .properties" should "should override defaults" in {
Settings.exclusively {
Settings.init(new File("src/test/resources/sample/settings/sample.properties"))
Settings.init(List(new File("src/test/resources/sample/settings/sample.properties")))
assertMigrationSample()
}
}
Expand All @@ -251,7 +262,7 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
GwenSettings.`gwen.auto.discover.meta` should be (true)
GwenSettings.`gwen.auto.trim.data.csv` should be (false)
GwenSettings.`gwen.auto.trim.data.json` should be (false)
GwenSettings.`gwen.behavior.rules` should be (BehaviorMode.lenient)
GwenSettings.`gwen.behavior.rules` should be (BehaviorMode.strict)
GwenSettings.`gwen.feature.dialect` should be ("en")
GwenSettings.`gwen.feature.failfast.enabled` should be (true)
GwenSettings.`gwen.feature.failfast.exit` should be (false)
Expand Down Expand Up @@ -323,8 +334,8 @@ class WebSettingsTest extends BaseTest with Matchers with MockitoSugar {
"Results files in gwen init conf" should "resolve" in {
Settings.exclusively {
withSetting("gwen.initDir", "gwen") {
Settings.init(new File("src/main/resources/init/gwen.conf"))
val resDir = "target/reports/results"
Settings.init(List(new File("src/main/resources/init/gwen.conf")))
val resDir = "gwen/output/reports/results"
val resFiles = GwenSettings.`gwen.report.results.files`(GwenOptions())
resFiles.size should be (7)
val fPassed = resFiles.find(_.id == "feature.passed").get
Expand Down
4 changes: 2 additions & 2 deletions src/test/scala/gwen/web/features/BaseFeatureTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import gwen.web.BaseTest
import gwen.web.GwenWebInterpreter

import gwen.core.GwenOptions
import gwen.core.BootstrapSettings
import gwen.core.GwenSettings
import gwen.core.Settings
import gwen.core.behavior.BehaviorMode
import gwen.core.status.Passed
Expand All @@ -39,7 +39,7 @@ abstract class BaseFeatureTest extends BaseTest {
if (dataFile.nonEmpty) args = args ++ Array("-i", dataFile.get)
if (BehaviorMode.isStrict) args = args ++ Array("-t", "~@Lenient")
args = args ++ features.toArray.asInstanceOf[Array[String]]
val options = GwenOptions(args, BootstrapSettings.`gwen.baseDir`)
val options = GwenOptions(args, GwenSettings.`gwen.baseDir`)
val interpreter = GwenWebInterpreter
interpreter.run(options, None) match {
case _: Passed => // woo hoo
Expand Down

0 comments on commit ce05d10

Please sign in to comment.