Index: ow/models/workout.py
===================================================================
--- ow/models/workout.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
+++ ow/models/workout.py	(revision fe6089a0a660861d9f0c69b51169b00fb023ab9d)
@@ -62,4 +62,8 @@
 
     @property
+    def owner(self):
+        return self.__parent__
+
+    @property
     def end(self):
         if not self.duration:
Index: ow/tests/models/test_workout.py
===================================================================
--- ow/tests/models/test_workout.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
+++ ow/tests/models/test_workout.py	(revision fe6089a0a660861d9f0c69b51169b00fb023ab9d)
@@ -59,4 +59,11 @@
     def test_workout_id(self, root):
         assert root['john']['1'].workout_id == '1'
+
+    def test_owner(self, root):
+        # workout with owner
+        assert root['john']['1'].owner == root['john']
+        # workout without owner
+        w = Workout()
+        assert w.owner is None
 
     def test_end(self, root):
Index: ow/tests/views/test_user.py
===================================================================
--- ow/tests/views/test_user.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
+++ ow/tests/views/test_user.py	(revision fe6089a0a660861d9f0c69b51169b00fb023ab9d)
@@ -122,5 +122,5 @@
         assert response.location == request.resource_url(root, 'login')
 
-    def test_dashboard_redirect_authenticated(self, root):
+    def test_dashboard_redirect_authenticated(self, root, john):
         """
         Authenticated user accesing the root object, send the user to her
@@ -131,11 +131,18 @@
         authenticated_userid, which cannot be easily set in the DummyRequest
         """
+        alt_request = DummyRequest()
         request = Mock()
         request.root = root
-        request.authenticated_userid = 'john'
-        request.resource_url.return_value = '/dashboard'
+        request.authenticated_userid = str(john.uid)
+        request.resource_url = alt_request.resource_url
         response = user_views.dashboard_redirect(root, request)
         assert isinstance(response, HTTPFound)
-        assert response.location == '/dashboard'
+        assert response.location == request.resource_url(john)
+        # if authenticated_userid is the id of an user that does not exist
+        # anymore, we send the user to the logout page
+        request.authenticated_userid = 'faked-uid'
+        response = user_views.dashboard_redirect(root, request)
+        assert isinstance(response, HTTPFound)
+        assert response.location == request.resource_url(root, 'logout')
 
     def test_dashboard(self, dummy_request, john):
@@ -287,4 +294,55 @@
         assert response['form'].errorlist() == html_error
         assert response['form'].errors_for('email') == [error]
+
+    def test_edit_profile_post_ok_picture_empty_bytes(
+            self, profile_post_request, john):
+        """
+        POST request with an empty picture, the content of
+        request['POST'].picture is a empty bytes string (b'') which triggers
+        a bug in formencode, we put a fix in place, test that
+        (more in ow.user.views.edit_profile)
+        """
+        # for the purposes of this test, we can mock the picture
+        picture = Mock()
+        john.picture = picture
+        request = profile_post_request
+        user = john
+        # Mimic what happens when a picture is not provided by the user
+        request.POST['picture'] = b''
+        response = user_views.edit_profile(user, request)
+        assert isinstance(response, HTTPFound)
+        assert response.location == request.resource_url(user, 'profile')
+        assert user.picture == picture
+
+    def test_edit_profile_post_ok_missing_picture(
+            self, profile_post_request, john):
+        """
+        POST request without picture
+        """
+        # for the purposes of this test, we can mock the picture
+        picture = Mock()
+        john.picture = picture
+        request = profile_post_request
+        user = john
+        # No pic is provided in the request POST values
+        del request.POST['picture']
+        response = user_views.edit_profile(user, request)
+        assert isinstance(response, HTTPFound)
+        assert response.location == request.resource_url(user, 'profile')
+        assert user.picture == picture
+
+    def test_edit_profile_post_ok_nickname(self, profile_post_request, john):
+        """
+        User with a nickname set saves profile without changing the profile,
+        we have to be sure there are no "nickname already in use" errors
+        """
+        request = profile_post_request
+        user = john
+        user.nickname = 'mr_jones'
+        # add the nickname, the default post request has not a nickname set
+        request.POST['nickname'] = 'mr_jones'
+        response = user_views.edit_profile(user, request)
+        assert isinstance(response, HTTPFound)
+        assert response.location == request.resource_url(user, 'profile')
 
     def test_change_password_get(self, dummy_request, john):
Index: ow/tests/views/test_workout.py
===================================================================
--- ow/tests/views/test_workout.py	(revision 31adfa57ce1ed36312e60622d6a3d0ddcfb98382)
+++ ow/tests/views/test_workout.py	(revision fe6089a0a660861d9f0c69b51169b00fb023ab9d)
@@ -164,4 +164,22 @@
         assert len(response['form'].form.errors) == 1
 
+    def test_add_workout_post_invalid_bytes(self, dummy_request):
+        """
+        POST request to add a workout, without uploading a tracking file,
+        which sends an empty bytes object (b'')
+        """
+        request = dummy_request
+        user = request.root['john']
+        request.method = 'POST'
+        request.POST = MultiDict({
+            'tracking_file': b'',
+            'submit': True,
+            })
+        assert len(request.root['john'].workouts()) == 1
+        response = workout_views.add_workout(user, request)
+        assert 'form' in response
+        # Only one required field in this case, the tracking file
+        assert len(response['form'].form.errors) == 1
+
     @pytest.mark.parametrize('filename', gpx_filenames)
     def test_add_workout_post_valid(self, filename, dummy_request):
@@ -256,4 +274,22 @@
         assert len(response['form'].form.errors) == 1
 
+    def test_update_workout_from_file_post_invalid_bytes(self, dummy_request):
+        """
+        POST request to update a workout, without uploading a tracking file,
+        which sends an empty bytes object (b'')
+        """
+        request = dummy_request
+        user = request.root['john']
+        workout = user.workouts()[0]
+        request.method = 'POST'
+        request.POST = MultiDict({
+            'tracking_file': b'',
+            'submit': True,
+            })
+        response = workout_views.update_workout_from_file(workout, request)
+        assert 'form' in response
+        # Only one required field in this case, the tracking file
+        assert len(response['form'].form.errors) == 1
+
     @pytest.mark.parametrize('filen', gpx_filenames)
     def test_update_workout_from_file_post_valid(self, filen, dummy_request):
