def test_recalculate(client): user = UserFactory() surface = SurfaceFactory(creator=user) topo1 = Topography1DFactory(surface=surface) topo2 = Topography1DFactory(surface=surface) func = AnalysisFunctionFactory(name="test function") impl = AnalysisFunctionImplementationFactory(function=func) client.force_login(user) with transaction.atomic(): # trigger "recalculate" for two topographies response = client.post( reverse('analysis:card-submit'), { 'function_id': func.id, 'subjects_ids_json': subjects_to_json([topo1, topo2]), 'function_kwargs_json': '{}' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request assert response.status_code == 200 # # Analysis objects should be there and marked for the user # analysis1 = Analysis.objects.get(function=func, topography=topo1) analysis2 = Analysis.objects.get(function=func, topography=topo2) assert user in analysis1.users.all() assert user in analysis2.users.all()
def test_card_templates_simple(client, mocker, handle_usage_statistics): """Check whether correct template is selected.""" # # Create database objects # password = "******" user = UserFactory(password=password) func1 = AnalysisFunctionFactory(card_view_flavor='power spectrum') topo1 = Topography1DFactory() # An analysis function with card_view_flavor='power spectrum' # should use the template which is needed for PowerSpectrumCardView. # # For the "detail" mode, there is an own template for power spectrum, # which should be returned. The the "list" mode, there is no # special template. Therefore, since "PowerSpectrumCardView" is # derived from the "PlotCardView" so far, the resulting # template should be 'plot_card_list.html'. assert client.login(username=user.username, password=password) response = client.post( reverse('analysis:card'), data={ 'function_id': func1.id, 'card_id': 'card', 'template_flavor': 'list', 'subjects_ids_json': subjects_to_json([topo1]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request assert response.template_name == ['analysis/plot_card_list.html'] response = client.post( reverse('analysis:card'), data={ 'function_id': func1.id, 'card_id': 'card', 'template_flavor': 'detail', 'subjects_ids_json': subjects_to_json([topo1]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request assert response.template_name == [ 'analysis/powerspectrum_card_detail.html' ]
def test_warnings_for_different_arguments(client, handle_usage_statistics): user = UserFactory() surf1 = SurfaceFactory(creator=user) surf2 = SurfaceFactory(creator=user) topo1a = Topography1DFactory(surface=surf1) topo1b = Topography1DFactory(surface=surf1) topo2a = Topography1DFactory(surface=surf2) func = AnalysisFunctionFactory() topo_impl = AnalysisFunctionImplementationFactory(function=func, subject_type=topo1a.get_content_type(), code_ref='topography_analysis_function_for_tests') surf_impl = AnalysisFunctionImplementationFactory(function=func, subject_type=surf1.get_content_type(), code_ref='surface_analysis_function_for_tests') # # Generate analyses for topographies with differing arguments # kwargs_1a = pickle.dumps(dict(a=1, b=2)) kwargs_1b = pickle.dumps(dict(a=1, b=3)) # differing from kwargs_1a! ana1a = TopographyAnalysisFactory(subject=topo1a, function=func, kwargs=kwargs_1a) ana1b = TopographyAnalysisFactory(subject=topo1b, function=func, kwargs=kwargs_1b) ana2a = TopographyAnalysisFactory(subject=topo2a, function=func) # default arguments # # Generate analyses for surfaces with differing arguments # kwargs_1 = pickle.dumps(dict(a=1, c=2)) kwargs_2 = pickle.dumps(dict(a=1, c=3)) # differing from kwargs_1a! ana1 = SurfaceAnalysisFactory(subject=surf1, function=func, kwargs=kwargs_1) ana2 = SurfaceAnalysisFactory(subject=surf2, function=func, kwargs=kwargs_2) client.force_login(user) # # request card, there should be warnings, one for topographies and one for surfaces # response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo1a, topo1b, topo2a, surf1, surf2]), 'function_id': func.id, 'card_id': "card-1", 'template_flavor': 'list' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) assert response.status_code == 200 assert_in_content(response, "Arguments for this analysis function differ among chosen " "subjects of type 'manager | topography'") assert_in_content(response, "Arguments for this analysis function differ among chosen " "subjects of type 'manager | surface'")
def send_card_request(): response = client.post( reverse('analysis:card'), data={ 'function_id': function.id, 'card_id': 'card', 'template_flavor': 'list', 'subjects_ids_json': subjects_to_json([topography]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request return response
def test_card_templates_for_power_spectrum(client, mocker, handle_usage_statistics): # # Create database objects # password = "******" user = UserFactory(password=password) func1 = AnalysisFunctionFactory(card_view_flavor='power spectrum') topo1 = Topography1DFactory() assert client.login(username=user.username, password=password) response = client.post( reverse('analysis:card'), data={ 'function_id': func1.id, 'card_id': 'card', 'template_flavor': 'list', 'subjects_ids_json': subjects_to_json([topo1]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request # we get the inherited "plot" template with "list" flavor, because power spectrum # hasn't got an own template with "list" flavor assert response.template_name == ['analysis/plot_card_list.html'] response = client.post( reverse('analysis:card'), data={ 'function_id': func1.id, 'card_id': 'card', 'template_flavor': 'detail', 'subjects_ids_json': subjects_to_json([topo1]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request # for the power spectrum detail card there should be an own template assert response.template_name == [ 'analysis/powerspectrum_card_detail.html' ]
def test_analysis_times(client, two_topos, django_user_model, handle_usage_statistics): user = django_user_model.objects.get(username='******') client.force_login(user) topo = Topography.objects.first() af = AnalysisFunction.objects.first() pickled_result = pickle.dumps({'name': 'test function', 'xlabel': 'x', 'ylabel': 'y', 'xunit': '1', 'yunit': '1', 'series': [], }) analysis = TopographyAnalysisFactory.create( subject=topo, function=af, task_state=Analysis.SUCCESS, start_time=datetime.datetime(2018, 1, 1, 12), end_time=datetime.datetime(2018, 1, 1, 13, 1, 1), # duration: 1 hour, 1 minute, 1 sec result=pickled_result, ) analysis.users.add(user) analysis.save() response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo]), 'function_id': af.id, 'card_id': "card-1", 'template_flavor': 'list', }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) assert response.status_code == 200 assert_in_content(response, "2018-01-01 12:00:00") # start_time assert_in_content(response, "1:01:01") # duration
def test_view_shared_analysis_results(client, handle_usage_statistics): password = '******' # # create database objects # user1 = UserFactory(password=password) user2 = UserFactory(password=password) surface1 = SurfaceFactory(creator=user1) surface2 = SurfaceFactory(creator=user2) # create topographies + functions + analyses func1 = AnalysisFunctionFactory() impl1 = AnalysisFunctionImplementationFactory(function=func1) # func2 = AnalysisFunctionFactory() # Two topographies for surface1 topo1a = Topography1DFactory(surface=surface1, name='topo1a') topo1b = Topography1DFactory(surface=surface1, name='topo1b') # One topography for surface2 topo2a = Topography1DFactory(surface=surface2, name='topo2a') # analyses, differentiate by start time analysis1a_1 = TopographyAnalysisFactory(subject=topo1a, function=func1, start_time=datetime.datetime(2019, 1, 1, 12)) analysis1b_1 = TopographyAnalysisFactory(subject=topo1b, function=func1, start_time=datetime.datetime(2019, 1, 1, 13)) analysis2a_1 = TopographyAnalysisFactory(subject=topo2a, function=func1, start_time=datetime.datetime(2019, 1, 1, 14)) # Function should have three analyses, all successful (the default when using the factory) assert func1.analysis_set.count() == 3 assert all(a.task_state == 'su' for a in func1.analysis_set.all()) # user2 shares surfaces, so user 1 should see surface1+surface2 surface2.share(user1) # # Now we change to the analysis card view and look what we get # assert client.login(username=user1.username, password=password) response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo1a, topo1b, topo2a]), 'function_id': func1.id, 'card_id': 1, 'template_flavor': 'list' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) # Function should still have three analyses, all successful (the default when using the factory) assert func1.analysis_set.count() == 3 assert all(a.task_state == 'su' for a in func1.analysis_set.all()) assert response.status_code == 200 # We should see start times of all three topographies assert_in_content(response, '2019-01-01 12:00:00') # topo1a assert_in_content(response, '2019-01-01 13:00:00') # topo1b assert_in_content(response, '2019-01-01 14:00:00') # topo2a client.logout() # # user 2 cannot access results from topo1, it is not shared # assert client.login(username=user2.username, password=password) response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo1a, topo1b, topo2a]), 'function_id': func1.id, 'card_id': 1, 'template_flavor': 'list' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) assert response.status_code == 200 assert_not_in_content(response, '2019-01-01 12:00:00') # topo1a assert_not_in_content(response, '2019-01-01 13:00:00') # topo1b assert_in_content(response, '2019-01-01 14:00:00') # topo2a client.logout()
def test_roughness_params_rounded(rf, mocker): from django.core.management import call_command call_command('register_analysis_functions') m = mocker.patch('topobank.analysis.functions.roughness_parameters') m.return_value = [ # some fake values for rounding { 'quantity': 'RMS Height', 'direction': None, 'from': 'area (2D)', 'symbol': 'Sq', 'value': np.float32(1.2345678), 'unit': 'm', }, { 'quantity': 'RMS Height', 'direction': 'x', 'from': 'profile (1D)', 'symbol': 'Rq', 'value': np.float32(8.7654321), 'unit': 'm', }, { 'quantity': 'RMS Curvature', 'direction': None, 'from': 'profile (1D)', 'symbol': '', 'value': np.float32(0.9), 'unit': '1/m', }, { 'quantity': 'RMS Slope', 'direction': 'x', 'from': 'profile (1D)', 'symbol': 'SΔq', 'value': np.float32(-1.56789), 'unit': 1, }, { 'quantity': 'RMS Slope', 'direction': 'y', 'from': 'profile (1D)', 'symbol': 'SΔq', 'value': np.float32('nan'), 'unit': 1, } ] topo = Topography2DFactory(size_x=1, size_y=1) func = AnalysisFunction.objects.get(name='Roughness parameters') TopographyAnalysisFactory(subject=topo, function=func) request = rf.post(reverse('analysis:card'), data={ 'function_id': func.id, 'card_id': 'card', 'template_flavor': 'list', 'subjects_ids_json': subjects_to_json([topo]), }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') request.user = topo.surface.creator request.session = {} rms_table_card_view = RoughnessParametersCardView.as_view() response = rms_table_card_view(request) assert response.status_code == 200 response.render() # we want rounding to 5 digits assert NUM_SIGNIFICANT_DIGITS_RMS_VALUES == 5 assert b"1.2346" in response.content assert b"8.7654" in response.content assert b"0.9" in response.content assert b"-1.5679" in response.content assert b"NaN" in response.content
def test_show_analyses_with_different_arguments(client, two_topos, django_user_model, handle_usage_statistics): user = django_user_model.objects.get(username='******') client.force_login(user) topo1 = Topography.objects.first() af = AnalysisFunction.objects.first() pickled_result = pickle.dumps({'name': 'test function', 'xlabel': 'x', 'ylabel': 'y', 'xunit': '1', 'yunit': '1', 'series': [], }) # # Create analyses for same function and topography but with different arguments # analysis = TopographyAnalysisFactory.create( subject=topo1, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({'bins': 10}), start_time=datetime.datetime(2018, 1, 1, 12), end_time=datetime.datetime(2018, 1, 1, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # save a second, which has a later start time analysis = TopographyAnalysisFactory.create( subject=topo1, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({'bins': 20}), start_time=datetime.datetime(2018, 1, 2, 12), end_time=datetime.datetime(2018, 1, 2, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # save a third, which has a later start time analysis = TopographyAnalysisFactory.create( subject=topo1, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({'bins': 30}), start_time=datetime.datetime(2018, 1, 3, 12), end_time=datetime.datetime(2018, 1, 3, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # # Check response, all three analyses should be shown # response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo1]), 'function_id': af.id, 'card_id': "card-1", 'template_flavor': 'list' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) assert response.status_code == 200 assert_in_content(response, "2018-01-01 12:00:00") assert_in_content(response, "2018-01-02 12:00:00") assert_in_content(response, "2018-01-03 12:00:00") # arguments should be visible in output import html.parser unescaped = html.unescape(response.content.decode()) assert str(dict(bins=10)) in unescaped assert str(dict(bins=20)) in unescaped
def test_show_only_last_analysis(client, two_topos, django_user_model, handle_usage_statistics): username = '******' user = django_user_model.objects.get(username=username) client.force_login(user) topo1 = Topography.objects.first() topo2 = Topography.objects.last() af = AnalysisFunction.objects.first() pickled_result = pickle.dumps({'name': 'test function', 'xlabel': 'x', 'ylabel': 'y', 'xunit': '1', 'yunit': '1', 'series': [], }) # # Topography 1 # analysis = TopographyAnalysisFactory.create( subject=topo1, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({}), start_time=datetime.datetime(2018, 1, 1, 12), end_time=datetime.datetime(2018, 1, 1, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # save a second only, which has a later start time analysis = TopographyAnalysisFactory.create( subject=topo1, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({}), start_time=datetime.datetime(2018, 1, 2, 12), end_time=datetime.datetime(2018, 1, 2, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # # Topography 2 # analysis = TopographyAnalysisFactory.create( subject=topo2, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({}), start_time=datetime.datetime(2018, 1, 3, 12), end_time=datetime.datetime(2018, 1, 3, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # save a second only, which has a later start time analysis = TopographyAnalysisFactory.create( subject=topo2, function=af, task_state=Analysis.SUCCESS, kwargs=pickle.dumps({}), start_time=datetime.datetime(2018, 1, 4, 12), end_time=datetime.datetime(2018, 1, 4, 13, 1, 1), result=pickled_result, ) analysis.users.add(user) analysis.save() # # Check response, for both topographies only the # latest results should be shown # response = client.post(reverse("analysis:card"), data={ 'subjects_ids_json': subjects_to_json([topo1, topo2]), 'function_id': af.id, 'card_id': 1, 'template_flavor': 'list' }, HTTP_X_REQUESTED_WITH='XMLHttpRequest', follow=True) assert response.status_code == 200 assert b"2018-01-02 12:00:00" in response.content assert b"2018-01-04 12:00:00" in response.content assert b"2018-01-01 12:00:00" not in response.content assert b"2018-01-03 12:00:00" not in response.content
def test_plot_card_if_no_successful_topo_analysis(client, handle_usage_statistics): # # Create database objects # password = "******" user = UserFactory(password=password) topography_ct = ContentType.objects.get_for_model(Topography) surface_ct = ContentType.objects.get_for_model(Surface) func1 = AnalysisFunctionFactory(card_view_flavor='power spectrum') AnalysisFunctionImplementationFactory(function=func1, subject_type=topography_ct) AnalysisFunctionImplementationFactory(function=func1, subject_type=surface_ct) surf = SurfaceFactory(creator=user) topo = Topography1DFactory(surface=surf) # also generates the surface # There is a successful surface analysis, but no successful topography analysis SurfaceAnalysisFactory(task_state='su', subject_id=topo.surface.id, subject_type_id=surface_ct.id, function=func1, users=[user]) # add a failed analysis for the topography TopographyAnalysisFactory(task_state='fa', subject_id=topo.id, subject_type_id=topography_ct.id, function=func1, users=[user]) assert Analysis.objects.filter(function=func1, subject_id=topo.id, subject_type_id=topography_ct.id, task_state='su').count() == 0 assert Analysis.objects.filter(function=func1, subject_id=topo.id, subject_type_id=topography_ct.id, task_state='fa').count() == 1 assert Analysis.objects.filter(function=func1, subject_id=topo.surface.id, subject_type_id=surface_ct.id, task_state='su').count() == 1 # login and request plot card view assert client.login(username=user.username, password=password) response = client.post( reverse('analysis:card'), data={ 'function_id': func1.id, 'card_id': 'card', 'template_flavor': 'list', 'subjects_ids_json': subjects_to_json([topo, topo.surface ]), # also request results for surface here }, HTTP_X_REQUESTED_WITH='XMLHttpRequest') # we need an AJAX request # should return without errors assert response.status_code == 200