Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add JuliaRunner to support Dash.jl integration tests - #1239

Merged
rpkyle merged 16 commits into
devfrom
add-julia-runner
May 19, 2020
Merged

Add JuliaRunner to support Dash.jl integration tests#1239
rpkyle merged 16 commits into
devfrom
add-julia-runner

Conversation

@rpkyle

@rpkylerpkyle commented May 9, 2020

Copy link
Copy Markdown
Contributor

This PR proposes to add a Julia application runner for Dash.jl, which will enable the contribution of integration tests for new and existing features for this implementation of the framework.

Here's a simple "smoke" test, replicating the same basic application currently in the R repository:

app = ''' using Dash
app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_div("Hello Dash.jl testing", id="container")
end
run_server(app, "127.0.0.1", 8050)
'''
def test_jstr001_jl_with_string(dashjl):
dashjl.start_server(app)
dashjl.wait_for_text_to_equal(
"#container", "Hello Dash.jl testing", timeout=1
) 

The test passes and works within a development branch of Dash.jl.

@waralex@alexcjohnson

Comment threaddash/testing/application_runners.py Outdated
self.proc = None

# pylint: disable=arguments-differ
def start(self, app, start_timeout=4, cwd=None):

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The start_timeout needs to be slightly longer than that used for R, since Julia takes a little longer to launch. This should be adequate, but we could always increase to 5 seconds if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to think about this timeout causing problems, especially as we never know what hardware we're on for CI and whether we have its full attention. If 4 "should be adequate" I'd probably give it 5 or 6 :)

@rpkylerpkyleMay 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being incredibly optimistic -- 5 or 6 seconds is sufficient for a local run, but within CircleCI it can take 10-12 seconds for Julia to start, and another 5-7 seconds for the HTTP.jl server to respond. I've set the timeouts to 30 seconds, since this seems to provide for consistently passing tests.

We could use 25 seconds, but there are occasional failures. I've tried to add code during the unit test run that triggers the precompilation there rather than within the integration test cycle, but it doesn't really help all that much. I'm not sure why it's slower within CircleCI, for now the conservative defaults will get the tests running.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. We don't need to address this now, this is fine for a POC and for running a few tests. But if we get to the point of running lots of integration tests we'll want to see if there's anything we can do to improve the startup time. Either speeding Julia startup in CI, or maybe there's a way we can start one Julia session and reuse it for multiple tests.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson Yeah, I'd like to see HTTP.jl start up a bit faster -- Julia is often faster than R or Python once the relevant code is loaded, but it does take more time to get going, and some of that is probably unavoidable. But 20-30 seconds for each integration test is going to eventually be problematic. I've wondered why we launch R repeatedly for integration testing, then kill the process.

Is there a reason we don't launch a single process, and then send an interrupt to the Dash server? Even if this itself returns an error, I feel that we should be able to muffle it so the chain of integration tests continues. That would have benefits for all backends, rather than just Julia, I think.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it can be as simple as interrupting the server, though this is what we do for the threaded runner in Python by adding an extra "stop" route. We'll also want to ensure that the environment gets cleaned out so tests don't depend on each other. So I think the solution is going to be different in each language, but anyway it doesn't seem like this overhead is that bothersome in R, whereas in Julia it's a much higher priority.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@rpkyle
rpkyleforce-pushed the add-julia-runner branch from 8a2229d to 63353aaCompareMay 11, 2020 19:15
@rpkyle

rpkyle commented May 12, 2020

Copy link
Copy Markdown
ContributorAuthor

Great that this has such an easy analog to RRunner! Can we 🌴 it? Have RRunner.start and JuliaRunner.start both call out to ProcessRunner._start_command or something? Looks like that would just need self.__class__.__name__ for the log messages and a command template string, then they're the same function.

Yes! Great idea. I've added an issue for that here so we can address this in a subsequent PR, as we discussed offline: #1242.

@rpkyle

rpkyle commented May 13, 2020

Copy link
Copy Markdown
ContributorAuthor

Not new here, but are we cleaning up the temp dirs we create for RRunner (and now JuliaRunner) tests? If we are I don't see it. Seems like we should be able to do that at the end of ProcessRunner.stop - ie if self.tmp_app_path exists at that point, shutil.rmtree it?

@alexcjohnson fixed in 62600db, log message added when in debug mode in 46a0cb8:

INFO dash.testing.application_runners:application_runners.py:84 killing the app runner
INFO dash.testing.application_runners:application_runners.py:222 proc.terminate with pid 911
DEBUG dash.testing.application_runners:application_runners.py:226 removing temporary app path /tmp/61b146c3774547b296b264ee0d46e1a8
INFO dash.testing.application_runners:application_runners.py:244 process stop completes!
INFO dash.testing.application_runners:application_runners.py:90 __exit__ complete

Comment threaddash/testing/application_runners.py Outdated
# try copying all valid sub folders (i.e. assets) in cwd to tmp
# note that the R assets folder name can be any valid folder name
assets = [
os.path.join(cwd, _)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies to R as well) does this whole asset-copying business belong in the if cwd block above? If we get here with no cwd it will be None, and interestingly os.listdir(None) succeeds (using the current dir I guess) but os.path.join(None, name) fails.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in 4c4d089

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just one minor comment that could be deferred to #1242 if you prefer.
💃

@rpkyle
rpkyle merged commit ebac7d4 into devMay 19, 2020
@rpkyle
rpkyle deleted the add-julia-runner branch May 19, 2020 03:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rpkyle@alexcjohnson