Skip to content

Commit 4acb7ab

Browse files
committed
Server: Updated unit test to ensure deletion of Settings instance
To ensure all tests are independent when run in one go, the ServerCompilerSettings singleton instance has to be completely dropped on the class tear down.
1 parent efee5d9 commit 4acb7ab

File tree

4 files changed

+103
-67
lines changed

4 files changed

+103
-67
lines changed

ardublocklyserver/compilersettings.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
# -*- coding: utf-8 -*-
2-
#
3-
# Save and retrieve the compiler settings into a text file.
4-
#
5-
# Copyright (c) 2017 carlosperate https://github.com/carlosperate/
6-
# Licensed under the Apache License, Version 2.0 (the "License"):
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# The ServerCompilerSettings is a singleton class maintains in memory, and
10-
# writes the Arduino IDE settings into a file.
11-
# On first invocation of the singleton it reads the settings from the file.
12-
#
2+
"""Save and retrieve the compiler settings into a text file.
3+
4+
Copyright (c) 2017 carlosperate https://github.com/carlosperate/
5+
Licensed under the Apache License, Version 2.0 (the "License"):
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
The ServerCompilerSettings is a singleton class maintains in memory, and writes
9+
the Arduino IDE settings into a file.
10+
On first invocation of the singleton it reads the settings from the file.
11+
"""
1312
from __future__ import unicode_literals, absolute_import, print_function
1413
import os
1514
import re
@@ -28,7 +27,7 @@ class ServerCompilerSettings(object):
2827
The class on first invocation tries to read the settings from the file, it
2928
keeps them in memory, and every time they are modified the changes are also
3029
written into the file.
31-
No compiler is part of the Python code, instead settings that
30+
No compiler is part of the Python code, instead settings that
3231
point to the local Arduino IDE and sketch are stored here.
3332
The public settings to set and get are:
3433
compiler_dir
@@ -105,8 +104,8 @@ def __initialise(self, settings_dir=None):
105104
self.__serial_port_key = None
106105
self.__serial_port_value = None
107106
if settings_dir:
108-
self.__settings_path = os.path.join(
109-
settings_dir, self.__settings_filename)
107+
self.__settings_path = os.path.join(settings_dir,
108+
self.__settings_filename)
110109
else:
111110
# If not set, the file path will be same location as the executed
112111
# python code that calls this class
@@ -212,7 +211,7 @@ def set_sketch_name(self, new_sketch_name):
212211
sketch_name = property(get_sketch_name, set_sketch_name)
213212

214213
def set_sketch_name_default(self):
215-
self.__sketch_name = 'ArdublocklySketch'
214+
self.__sketch_name = 'ArdublocklySketch'
216215

217216
def set_sketch_name_from_file(self, new_sketch_name):
218217
""" Only accept letters, numbers, underscores and dashes. """
@@ -546,18 +545,15 @@ def save_settings(self):
546545

547546
# Set the path and create/overwrite the file
548547
try:
549-
settings_file = codecs.open(
550-
self.__settings_path, 'wb+', encoding='utf-8')
551-
try:
552-
settings_parser.write(settings_file)
553-
print('Settings file saved to:\n\t%s' % self.__settings_path)
554-
sys.stdout.flush()
555-
finally:
556-
settings_file.close()
548+
with codecs.open(self.__settings_path, 'wb+', encoding='utf-8') as\
549+
config_file:
550+
settings_parser.write(config_file)
557551
except Exception as e:
558-
print(e)
559-
print('Unable to write the settings file to:\n\t%s' %
560-
self.__settings_path)
552+
print('%s\nUnable to write the settings file to:\n\t%s' %
553+
(self.__settings_path, str(e)))
554+
else:
555+
print('Settings file saved to:\n\t%s' % self.__settings_path)
556+
sys.stdout.flush()
561557

562558
def read_settings(self):
563559
"""
@@ -600,8 +596,8 @@ def get_settings_file_data(self):
600596
settings_dict = {}
601597
settings_parser = configparser.ConfigParser()
602598
try:
603-
settings_parser.read_file(
604-
codecs.open(self.__settings_path, 'r', 'utf8'))
599+
with codecs.open(self.__settings_path, 'r', 'utf8') as config_file:
600+
settings_parser.read_file(config_file)
605601
settings_dict['arduino_exec_path'] =\
606602
settings_parser.get('Arduino_IDE', 'arduino_exec_path')
607603
settings_dict['arduino_board'] =\
@@ -621,6 +617,12 @@ def get_settings_file_data(self):
621617
settings_dict = None
622618
return settings_dict
623619

620+
def get_settings_file_path(self):
621+
return self.__settings_path
622+
624623
def delete_settings_file(self):
624+
success = False
625625
if os.path.exists(self.__settings_path):
626626
os.remove(self.__settings_path)
627+
success = True
628+
return success

ardublocklyserver/tests/actions_test.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"""
88
from __future__ import unicode_literals, absolute_import, print_function
99
import os
10+
import gc
1011
import sys
1112
import shutil
1213
import codecs
@@ -47,11 +48,19 @@ def setUpClass(cls):
4748
if os.path.isdir(cls.temp_folder):
4849
raise Exception('Directory %s already exists.' % cls.temp_folder)
4950
os.makedirs(cls.temp_folder)
51+
# Create settings file and check it's a new instance by looking at path
5052
cls.settings = ServerCompilerSettings(cls.temp_folder)
53+
if cls.temp_folder not in cls.settings.get_settings_file_path():
54+
raise Exception('Settings file not created in temp folder:\n'
55+
'\t%s' % cls.settings.get_settings_file_path())
5156

5257
@classmethod
5358
def tearDownClass(cls):
5459
"""Deletes the previously created temporary folder."""
60+
cls.settings._drop()
61+
del cls.settings
62+
cls.settings = None
63+
gc.collect()
5564
if os.path.isdir(cls.temp_folder):
5665
shutil.rmtree(cls.temp_folder)
5766

@@ -67,23 +76,6 @@ def tearDown(self):
6776
if os.path.isdir(self.__class__.temp_folder):
6877
shutil.rmtree(self.__class__.temp_folder)
6978

70-
#
71-
# Helper functions
72-
#
73-
def delete_default_settings_file(self):
74-
"""
75-
Checks if there is a settings file in the default location and deletes
76-
it if it finds it.
77-
This will DELETE a file from the directory this script is called !!!
78-
"""
79-
# Accessing the class static variable does not initialise the singleton
80-
settings_file = os.path.normpath(os.path.join(
81-
self.temp_folder,
82-
ServerCompilerSettings._ServerCompilerSettings__settings_filename))
83-
if os.path.exists(settings_file):
84-
print('Removing settings file from %s' % settings_file)
85-
os.remove(settings_file)
86-
8779
#
8880
# Command line tests
8981
#

ardublocklyserver/tests/compilersettings_test.py

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# -*- coding: utf-8 -*-
2-
#
3-
# Unit test for the compilersettings module.
4-
#
5-
# Copyright (c) 2015 carlosperate https://github.com/carlosperate/
6-
# Licensed under the Apache License, Version 2.0 (the "License"):
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
2+
"""Unit test for the ServerCompilerSettings class.
3+
4+
Copyright (c) 2015 carlosperate https://github.com/carlosperate/
5+
Licensed under the Apache License, Version 2.0 (the "License"):
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
"""
98
from __future__ import unicode_literals, absolute_import, print_function
109
import os
10+
import gc
1111
import sys
12+
import shutil
1213
import unittest
1314
try:
1415
import mock
@@ -20,47 +21,76 @@
2021
try:
2122
from ardublocklyserver.compilersettings import ServerCompilerSettings
2223
except ImportError:
23-
import sys
2424
file_dir = os.path.dirname(os.path.realpath(__file__))
2525
package_dir = os.path.dirname(os.path.dirname(file_dir))
2626
sys.path.insert(0, package_dir)
2727
from ardublocklyserver.compilersettings import ServerCompilerSettings
2828

2929

3030
class ServerCompilerSettingsTestCase(unittest.TestCase):
31-
"""
32-
Tests for ServerCompilerSettings
33-
"""
31+
"""Tests for ServerCompilerSettings."""
32+
33+
settings = None
34+
temp_folder = None
35+
36+
#
37+
# Test fixtures
38+
#
39+
@classmethod
40+
def setUpClass(cls):
41+
"""Create a temporary folder to play round."""
42+
cls.temp_folder = os.path.join(
43+
os.path.abspath(os.path.dirname(__file__)),
44+
'TestTemp_compilersettings')
45+
if os.path.isdir(cls.temp_folder):
46+
raise Exception('Directory %s already exists.' % cls.temp_folder)
47+
os.makedirs(cls.temp_folder)
48+
# Create settings file and check it's a new instance by looking at path
49+
cls.settings = ServerCompilerSettings(cls.temp_folder)
50+
if cls.temp_folder not in cls.settings.get_settings_file_path():
51+
raise Exception('Settings file not created in temp folder:\n'
52+
'\t%s' % cls.settings.get_settings_file_path())
53+
54+
@classmethod
55+
def tearDownClass(cls):
56+
"""Deletes the previously created temporary folder and settings."""
57+
cls.settings._drop()
58+
del cls.settings
59+
cls.settings = None
60+
gc.collect()
61+
if os.path.isdir(cls.temp_folder):
62+
shutil.rmtree(cls.temp_folder)
3463

3564
#
3665
# Helper functions
3766
#
3867
def get_default_settings_file_dir(self):
68+
return os.path.normpath(
69+
self.settings._ServerCompilerSettings__settings_path)
3970
# The default location from the ServerCompilerSettings class is the
4071
# following, so if that changes in the class it needs to change here !!!
41-
default_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
72+
#default_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
4273
# Accessing the class static variable does not initialise the singleton
43-
return os.path.normpath(os.path.join(
44-
default_dir,
45-
ServerCompilerSettings._ServerCompilerSettings__settings_filename))
74+
#return os.path.normpath(os.path.join(
75+
# default_dir,
76+
# ServerCompilerSettings._ServerCompilerSettings__settings_filename))
4677

4778
def delete_default_settings_file(self):
4879
"""
4980
Checks if there is a settings file in the default location and deletes
5081
it if it finds it.
5182
This will DELETE a file from the directory this script is called !!!
5283
"""
53-
settings_file = self.get_default_settings_file_dir()
54-
if os.path.exists(settings_file):
55-
print('Removing settings file from %s' % settings_file)
56-
os.remove(settings_file)
84+
print('Removing settings file from %s' % os.path.normpath(
85+
self.settings._ServerCompilerSettings__settings_filename))
86+
self.settings.delete_settings_file()
5787

5888
def new_ServerCompilerSettings_instance(self):
5989
"""
6090
Drops the current ServerCompilerSettings instance and creates a new one.
6191
"""
6292
ServerCompilerSettings()._drop()
63-
return ServerCompilerSettings()
93+
return ServerCompilerSettings(self.temp_folder)
6494

6595
#
6696
# Testing the class singleton property

ardublocklyserver/tests/sketchcreator_test.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#
99
from __future__ import unicode_literals, absolute_import
1010
import os
11+
import gc
1112
import time
1213
import codecs
1314
import shutil
@@ -21,15 +22,17 @@
2122
package_dir = os.path.dirname(os.path.dirname(file_dir))
2223
sys.path.insert(0, package_dir)
2324
from ardublocklyserver import sketchcreator
25+
from ardublocklyserver.compilersettings import ServerCompilerSettings
2426

2527

2628
class SketchCreatorTestCase(unittest.TestCase):
27-
"""
28-
Tests for SketchCreator class.
29+
"""Tests for SketchCreator class.
30+
2931
Rather than mocking around with os module it creates 'safe' folder inside
3032
the test directory where it can create and delete files.
3133
"""
3234

35+
settings = None
3336
temp_folder = None
3437

3538
#
@@ -48,10 +51,19 @@ def setUpClass(cls):
4851
cls.default_sketch_path = os.path.join(
4952
cls.temp_folder, sketchcreator.default_sketch_name,
5053
'%s.ino' % sketchcreator.default_sketch_name)
54+
# Create settings file and check it's a new instance by looking at path
55+
cls.settings = ServerCompilerSettings(cls.temp_folder)
56+
if cls.temp_folder not in cls.settings.get_settings_file_path():
57+
raise Exception('Settings file not created in temp folder:\n'
58+
'\t%s' % cls.settings.get_settings_file_path())
5159

5260
@classmethod
5361
def tearDownClass(cls):
5462
"""Deletes the previously created temporary folder."""
63+
cls.settings._drop()
64+
del cls.settings
65+
cls.settings = None
66+
gc.collect()
5567
if os.path.isdir(cls.temp_folder):
5668
shutil.rmtree(cls.temp_folder)
5769

0 commit comments

Comments
 (0)