Ignore:
Timestamp:
9 May 2012, 16:43:10 (13 years ago)
Author:
uli
Message:

Backup student data when a student is deleted (blocking of student_id yet missing).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_student.py

    r8194 r8403  
    1818"""Tests for students and related.
    1919"""
     20import os
     21import re
     22from cStringIO import StringIO
    2023from datetime import tzinfo
     24from zope.component import getUtility
    2125from zope.component.interfaces import IFactory
    2226from zope.interface import verify
    23 from waeup.kofa.students.student import Student, StudentFactory
     27from waeup.kofa.interfaces import IExtFileStore, IFileStoreNameChooser
     28from waeup.kofa.students.export import EXPORTER_NAMES
     29from waeup.kofa.students.student import (
     30    Student, StudentFactory, handle_student_removed)
    2431from waeup.kofa.students.studycourse import StudentStudyCourse
    2532from waeup.kofa.students.studylevel import StudentStudyLevel, CourseTicket
    2633from waeup.kofa.students.payments import StudentPaymentsContainer
    2734from waeup.kofa.students.accommodation import StudentAccommodation, BedTicket
    28 from waeup.kofa.applicants.interfaces import IApplicantBaseData
    2935from waeup.kofa.students.interfaces import (
    30     IStudent, IStudentStudyCourse, IStudentPaymentsContainer, IStudentAccommodation,
    31     IStudentStudyLevel, ICourseTicket, IBedTicket)
     36    IStudent, IStudentStudyCourse, IStudentPaymentsContainer,
     37    IStudentAccommodation, IStudentStudyLevel, ICourseTicket, IBedTicket)
     38from waeup.kofa.students.tests.test_batching import StudentImportExportSetup
    3239from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
    3340from waeup.kofa.university.department import Department
     
    8390        return
    8491
     92class StudentRemovalTests(StudentImportExportSetup):
     93    # Test handle_student_removed
     94    #
     95    # This is a complex action updating several CSV files and moving
     96    # stored files to a backup location.
     97    #
     98    # These tests make no assumptions about the CSV files except that
     99    # they contain a deletion timestamp at end of each data row
     100
     101    layer = FunctionalLayer
     102
     103    def setUp(self):
     104        super(StudentRemovalTests, self).setUp()
     105        self.setup_for_export()
     106        return
     107
     108    def create_passport_img(self, student):
     109        # create some faked passport file for `student`
     110        storage = getUtility(IExtFileStore)
     111        file_id = IFileStoreNameChooser(student).chooseName(
     112            attr='passport.jpg')
     113        storage.createFile(file_id, StringIO('I am a fake image.'))
     114
     115    def test_backup_single_student_data(self):
     116        # when a single student is removed, the data is backed up.
     117        self.setup_student(self.student)
     118        # Add a fake image
     119        self.create_passport_img(self.student)
     120        handle_student_removed(self.student, None)
     121        del_dir = self.app['datacenter'].deleted_path
     122        del_img_path = os.path.join(
     123            del_dir, 'media', 'students', 'A', 'A111111',
     124            'passport_A111111.jpg')
     125
     126        # The image was copied over
     127        self.assertTrue(os.path.isfile(del_img_path))
     128        self.assertEqual(
     129            open(del_img_path, 'rb').read(),
     130            'I am a fake image.')
     131
     132        # The student data were put into CSV files
     133        for name in EXPORTER_NAMES:
     134            csv_path = os.path.join(del_dir, '%s.csv' % name)
     135            self.assertTrue(os.path.isfile(csv_path))
     136            contents = open(csv_path, 'rb').read().split('\r\n')
     137            # We expect 3 lines output including a linebreak at end of file.
     138            self.assertEqual(len(contents), 3)
     139        return
     140
     141    def test_backup_append_csv(self):
     142        # when several students are removed, existing CSVs are appended
     143        self.setup_student(self.student)
     144        # Add a fake image
     145        self.create_passport_img(self.student)
     146        del_dir = self.app['datacenter'].deleted_path
     147        # put fake data into students.csv with trailing linebreak
     148        students_csv = os.path.join(del_dir, 'students.csv')
     149        open(students_csv, 'wb').write('line1\r\nline2\r\n')
     150        handle_student_removed(self.student, None)
     151        contents = open(students_csv, 'rb').read().split('\r\n')
     152        # there should be 4 lines in result csv (including trailing linebreak)
     153        self.assertEqual(len(contents), 4)
     154        return
     155
     156    def test_old_files_removed(self):
     157        # make sure old files are not accessible any more
     158        self.setup_student(self.student)
     159        # Add a fake image
     160        self.create_passport_img(self.student)
     161        # make sure we can access the image before removal
     162        file_store = getUtility(IExtFileStore)
     163        image = file_store.getFileByContext(self.student, attr='passport.jpg')
     164        self.assertTrue(image is not None)
     165
     166        # remove image (hopefully)
     167        handle_student_removed(self.student, None)
     168
     169        # the is not accessible anymore
     170        image = file_store.getFileByContext(self.student, attr='passport.jpg')
     171        self.assertEqual(image, None)
     172        return
     173
     174    def test_csv_file_entries_have_timestamp(self):
     175        # each row in written csv files has a ``del_date`` column to
     176        # tell when the associated student was deleted
     177        self.setup_student(self.student)
     178        del_dir = self.app['datacenter'].deleted_path
     179        students_csv = os.path.join(del_dir, 'students.csv')
     180        handle_student_removed(self.student, None)
     181        contents = open(students_csv, 'rb').read().split('\r\n')
     182        # the CSV header ends with a ``del_date`` column
     183        self.assertTrue(contents[0].endswith(',del_date'))
     184        # each line ends with an UTC timestamp
     185        timestamp = contents[1][-23:]
     186        self.assertTrue(re.match(
     187            '^\d\d-\d\d-\d\d \d\d:\d\d:\d\d\+00:00$', timestamp))
     188        return
     189
     190
    85191class StudentFactoryTest(FunctionalTestCase):
    86192
Note: See TracChangeset for help on using the changeset viewer.