Вы могли использовать этот метод 1 глоток>, который использует ClassLoader
.
/**
* Scans all classes accessible from the context class loader which belong to the given package and subpackages.
*
* @param packageName The base package
* @return The classes
* @throws ClassNotFoundException
* @throws IOException
*/
private static Class[] getClasses(String packageName)
throws ClassNotFoundException, IOException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
assert classLoader != null;
String path = packageName.replace('.', '/');
Enumeration resources = classLoader.getResources(path);
List dirs = new ArrayList();
while (resources.hasMoreElements()) {
URL resource = resources.nextElement();
dirs.add(new File(resource.getFile()));
}
ArrayList classes = new ArrayList();
for (File directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
return classes.toArray(new Class[classes.size()]);
}
/**
* Recursive method used to find all classes in a given directory and subdirs.
*
* @param directory The base directory
* @param packageName The package name for classes found inside the base directory
* @return The classes
* @throws ClassNotFoundException
*/
private static List findClasses(File directory, String packageName) throws ClassNotFoundException {
List classes = new ArrayList();
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
assert !file.getName().contains(".");
classes.addAll(findClasses(file, packageName + "." + file.getName()));
} else if (file.getName().endsWith(".class")) {
classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
}
}
return classes;
}
__________
1 глоток> Этот метод был взят первоначально от http://snippets.dzone.com/posts/show/4831 , который был , заархивировал интернет-Архивом, как связано с теперь. Отрывок также доступен в https://dzone.com/articles/get-all-classes-within-package.
Мне нужно было что-то подобное для функционального тестирования, которое я выполняю с помощью носа. В конце концов я пришел к такому выводу:
def raw_print(str, *args):
out_str = str % args
sys.stdout.write(out_str)
class DeferredAsserter(object):
def __init__(self):
self.broken = False
def assert_equal(self, expected, actual):
outstr = '%s == %s...' % (expected, actual)
raw_print(outstr)
try:
assert expected == actual
except AssertionError:
raw_print('FAILED\n\n')
self.broken = True
except Exception, e:
raw_print('ERROR\n')
traceback.print_exc()
self.broken = True
else:
raw_print('PASSED\n\n')
def invoke(self):
assert not self.broken
Другими словами, он распечатывает строки, указывающие, прошел ли тест или нет. В конце теста вы вызываете метод invoke, который фактически выполняет реальное утверждение. Это определенно нежелательно, но я не видел фреймворка для тестирования Python, который мог бы обрабатывать такого рода тестирование. Я также не придумал, как написать плагин для носа, чтобы делать такие вещи. : - /
Как ни странно, похоже, что вы ищете что-то вроде моего claft
(командная строка и тестер фильтров). Что-то вроде этого, но гораздо более зрелое.
claft
- это (пока) просто игрушка, которую я написал, чтобы помочь студентам с упражнениями по программированию. Идея состоит в том, чтобы предоставить упражнениям простые файлы конфигурации, которые представляют требования программы в терминах, которые достаточно удобочитаемы (и декларативны, а не программны), а также подходят для автоматического тестирования.
claft
запускает все определенные тесты. , предоставление аргументов и входных данных каждому, проверка кодов возврата и сопоставление выходных данных ( stdout
) и сообщений об ошибках ( stderr
) по шаблонам регулярных выражений. Он собирает все ошибки в списке и печатает весь список в конце каждого набора.
Он еще НЕ выполняет произвольные диалоги последовательностей ввода / вывода. Пока он просто загружает данные, а затем считывает все данные / ошибки. Он также не реализует тайм-ауты и, по сути, даже не фиксирует неудачные попытки выполнения. (Я ведь говорил, что это просто игрушка, не так ли?). Я также еще не реализовал поддержку скриптов Setup, Teardown и External Check (хотя у меня есть планы сделать это).
Предложение Брайана о «структуре роботов» может быть лучше для ваших нужд; хотя беглый взгляд на него подсказывает, что для моих целей он гораздо сложнее, чем я хочу. (Мне нужно, чтобы все было достаточно простым, чтобы студенты, не знакомые с программированием, могли сосредоточиться на своих упражнениях и не тратить много времени на борьбу с настройкой своего тестового снаряжения).
Вы можете взглянуть на claft
и использовать его или получить оттуда собственное решение (оно лицензировано BSD). Очевидно, вы можете внести свой вклад. (Он находится на [bitbucket]: ( http://www.bitbucket.org/ ), так что вы можете использовать Mercurial для клонирования и форка своего собственного репозитория ... и отправить «запрос на перенос», если вы когда-нибудь захочу, чтобы я посмотрел на слияние ваших изменений с моим репо).
С другой стороны, возможно, я неправильно понимаю ваш вопрос.
буду рад внести свой вклад. (Он находится на [bitbucket]: ( http://www.bitbucket.org/ ), так что вы можете использовать Mercurial для клонирования и форка своего собственного репозитория ... и отправить «запрос на перенос», если вы когда-нибудь захочу, чтобы я посмотрел на слияние ваших изменений с моим репо).С другой стороны, возможно, я неправильно понимаю ваш вопрос.
буду рад внести свой вклад. (Он находится на [bitbucket]: ( http://www.bitbucket.org/ ), так что вы можете использовать Mercurial для клонирования и форка своего собственного репозитория ... и отправить «запрос на перенос», если вы когда-нибудь захочу, чтобы я посмотрел на слияние ваших изменений с моим репо).С другой стороны, возможно, я неправильно понимаю ваш вопрос.
Вы просили совета, поэтому я предлагаю каркас робота .
Обновление:
Судя по комментариев, похоже, что у многих людей проблемы с XML. Я знаю, что сейчас это круто, и у него есть свои проблемы, но в данном случае я думаю, что это работает. Одна из других причин, по которой я выбрал его, заключается в том, что существует множество библиотек для его анализа, что может облегчить жизнь.
Другая ключевая концепция заключается в том, что информация действительно нереляционная . Так что да, вы можете хранить данные в любом конкретном примере в кучу разных таблиц с большим количеством объединений, но это больно. Но если бы я продолжал приводить вам несколько другие примеры, держу пари, вам придется до бесконечности изменять свой дизайн. Я не думаю, что добавление таблиц и изменение сложных операторов SQL - это очень весело. Так что немного расстраивает то, что за комментарий @ scheibk проголосовали.
Исходное сообщение:
Я думаю, что проблема, с которой вы можете столкнуться с хранением информации о квестах в базе данных, заключается в том, что она не совсем реляционная (то есть не очень легко помещается в таблицу). Возможно, именно поэтому у вас возникли проблемы с созданием таблиц для данных.
С другой стороны, если вы поместите информацию о вашем задании непосредственно в код, это означает, что вам придется редактировать код и перекомпилировать каждый раз, когда вы хотите добавить квест. Хромой.
Так что, если бы я был на вашем месте, я мог бы подумать о сохранении информации о моих квестах в XML-файле или в чем-то подобном. Я знаю, что это универсальное решение для чего угодно, но в данном случае оно мне подходит. XML действительно создан для хранения не связанных и / или иерархических данных, точно так же, как материал, который вам нужно хранить для вашего квеста.
Резюме: вы можете придумать свою собственную схему, создать свой XML-файл, а затем загрузить его каким-то образом во время выполнения (или даже сохранить XML в базе данных).
Пример XML:
Почему бы и нет (в unittest
, но это должно работать в любой структуре):
class multiTests(MyTestCase):
def testMulti(self, tests):
tests( a == b )
tests( frobnicate())
...
предполагая, что ваш реализованный MyTestCase, так что функция заключена в
testlist = []
x.testMulti(testlist.append)
assert all(testlist)