Closed mitch-shiver closed 1 year ago
As a web application, your code might be running in a subprocess. Have you enabled subprocess measurement? https://coverage.readthedocs.io/en/latest/subprocess.html
Alternately, you might be able to ask Dash to not spawn subprocesses. Let me know if it worked.
Hi Ned, I instrumented to detect any child processes running, once before launching the app and then each time the interval times out, code and results below. I believe this means there are no subprocesses running. However I will try the other option you recommended (enable subprocess measurement) and respond back with any results... Code updates:
@app.callback(
Output('statsTable', 'data'),
Input('hiddenDivRefreshUI', 'n_intervals'))
def updateTextUpdate(ack):
print('made it here')
print('after: {}'.format(active_children()))
stats = [['joe',17],['bob',28],['bill',66],['mike',4]]
dfStats = pd.DataFrame(stats, columns=['Name','Stat'])
currentData = dfStats.to_dict('records')
return currentData
if __name__ == '__main__':
print('before: {}'.format(active_children()))
app.run_server(host='0.0.0.0', debug=True)
Output:
To your knowledge has anyone used the coverage module in conjunction with Dash apps?
Thanks, Mitch
On Wednesday, July 26, 2023 at 01:14:45 PM PDT, Ned Batchelder ***@***.***> wrote:
As a web application, your code might be running in a subprocess. Have you enabled subprocess measurement? https://coverage.readthedocs.io/en/latest/subprocess.html
Alternately, you might be able to ask Dash to not spawn subprocesses. Let me know if it worked.
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
hmm, I enabled subprocess coverage management using the instructions in the help files, details below, but I do not believe that Dash is kicking off any subprocesses. I reached out to Plotly to ask about it, will update when they respond. However using the criteria you suggested, the issue does not seem to be subprocess-related. Any other ideas? I was hoping to use coverage to instrument a large Dash Python app to help understand code coverage, but a typical Dash app is 70-80% callbacks...
Code update:
import dash
import dash_table
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
import pandas as pd
from multiprocessing import active_children
def getDataTable():
stats = [['joe',17],['bob',28],['bill',66],['mike',4]]
dfStats = pd.DataFrame(stats, columns=['Name','Stat'])
return html.Div([dash_table.DataTable(
id='statsTable',
columns=[{"name": i, "id": i} for i in dfStats.columns],
data=dfStats.to_dict('records'),),
html.Div(dcc.Interval(id='hiddenDivRefreshUI', interval=1000, n_intervals=0, disabled = False))])
app = dash.Dash(__name__)
app.layout = getDataTable()
### This callback updates the update text
@app.callback(
Output('statsTable', 'data'),
Input('hiddenDivRefreshUI', 'n_intervals'))
def updateTextUpdate(ack):
print('made it here')
print('after: {}'.format(active_children()))
stats = [['joe',17],['bob',28],['bill',66],['mike',4]]
dfStats = pd.DataFrame(stats, columns=['Name','Stat'])
currentData = dfStats.to_dict('records')
return currentData
if __name__ == '__main__':
print('before: {}'.format(active_children()))
app.run_server(host='0.0.0.0', debug=True)
sitecustomize.py contents:
import coverage
print('Launching subprocess coverage settings...')
coverage.process_startup()
Report output:
$ coverage report -m
Launching subprocess coverage settings...
Name Stmts Miss Branch BrPart Cover Missing
--------------------------------------------------------
testapp.py 21 6 2 0 74% 27-32
--------------------------------------------------------
TOTAL 21 6 2 0 74%
Command Line output:
$ coverage run testapp.py
Launching subprocess coverage settings...
before: []
Dash is running on http://0.0.0.0:8050/
* Serving Flask app 'testapp' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
Launching subprocess coverage settings...
before: []
made it here
after: []
made it here
after: []
made it here
after: []
Try changing this line:
app.run_server(host='0.0.0.0', debug=True)
to:
app.run_server(host='0.0.0.0', debug=True, dev_tools_hot_reload=False)
Hi @nedbat,
I made that change, cleared the existing report and reran the coverage execution, but the outcome report was the same as before (below). I am adding a second callback now to see if all callbacks are ignored this way or if something is special about this callback. To your knowledge has anyone used the coverage module in conjunction with Dash apps?
Output:
$ coverage report -m
Name Stmts Miss Cover Missing
------------------------------------------
testapp.py 24 6 75% 27-32
------------------------------------------
TOTAL 24 6 75%
Experimenting with your code showed the problem: debug=True
makes dash run the code inside a debugger. That clobbers coverage's trace function, so the code isn't measured. If you change to this, the code will be 100% covered:
app.run_server(host='0.0.0.0', debug=False)
Awesome, works!
$ coverage report -m
Name Stmts Miss Cover Missing
------------------------------------------
testapp.py 24 0 100%
------------------------------------------
TOTAL 24 0 100%
Hi @nedbat great tool, thanks for making it available!
I am using Python 3.9 along with the Dash module from Plotly to create a web app, but once I have installed coverage (v7.2.7), for some reason the Dash callback that I created is not counted as covered by the output report, even though I have clear evidence that the callback function itself is getting called as expected.
Code:
Normal execution:
python testapp.py
Coverage execution:
coverage run testapp.py
Expected behavior: When the webpage at http://0.0.0.0:8050 is loaded, the callback function (updateTextUpdate) is called every second as a result of the dcc.Interval setting. I can see this is happening because I observe the 'made it here' text appearing in the command prompt window where I have launched the app (and I see it for both the normal and coverage execution above). However, the output report (below) shows this code as missed/missing. I would expect that it shows as covered.
Report output:
Output of
coverage debug sys
:Output of
pip freeze
: