111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
1

Как правильно отделить пакет библиотеки от тестов?

10.04.2014, 12:28. Показов 1442. Ответов 15
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Поделитесь, пожалуйста, опытом: кто как организует проект с тестами?

Пока пишу тесты прямо в коде и запускаю их из main. Но скоро собирать все в пакет, и не хочется тянуть Tasty в зависимости.

Кто как поступает? Использую Tasty.HUnit.

Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.04.2014, 12:28
Ответы с готовыми решениями:

Как правильно отделить логику от вида
Есть таблица в БД состоящая из четырех столбцов н.п. ID SURNAME NAME PHONE 1 Петров Петя ...

Инкапсуляция или как правильно отделить логику
Делаю проект в WPF(но это не важно). Вопрос таков: может ли класс где обработчики всех событий...

Как правильно присоединить пакет java.lang? (компиляция без инструкции import)
Друзья! У меня в книжке написано: Вот пытаюсь import javax.swing.*; Заменить на...

Программа для тестов - как грамотно подойти к редактированию тестов
Что я пишу: Вот пишу приложение для создания тестов, dll с классами самих тестов и приложение,...

15
Модератор
Эксперт функциональных языков программированияЭксперт Python
36527 / 19831 / 4155
Регистрация: 12.02.2012
Сообщений: 32,963
Записей в блоге: 13
10.04.2014, 12:39 2
А что в этой проблеме специфически Хаскелловское? Зачем держать тесты вместе с рабочим кодом?
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 12:58  [ТС] 3
Цитата Сообщение от Catstail Посмотреть сообщение
А что в этой проблеме специфически Хаскелловское?
Пути до модулей у него не интуитивные.
Использую Sublime Text 2. В нем на F9 забиндил runhaskell с текущим файлом. Удобно: написал, нажал F9 - проверилось.
Начал оформлять в пакет, появилось два варианта:
1. кабал собирает пакет, но при этом в SublimeText runhaskell по F9 выдает, что не может import Hs2GCode.Common
2. могу переименовать пакет на Common. F9 работает, но теперь кабал не может собрать пакет.
С тестами еще не разобрался. runhaskell Setup test -ломится искать test.exe. Но это дело техники.

Вообщем, хочу, чтобы можно было каждый файлик править, нажать F9, проверить. А потом выйти и пнуть кабал, чтобы он собрал пакет. Не получается.
1
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 14:19 4
Лучший ответ Сообщение было отмечено aaleksander как решение

Решение

Цитата Сообщение от aaleksander Посмотреть сообщение
Поделитесь, пожалуйста, опытом: кто как организует проект с тестами?
Cabal to rescue!

Рассмотрим простой пример: библиотека, предоставляющая тип «множество».

src/Data/MySet.hs содержит определение самого типа и операций над ним.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
module Data.MySet
    ( MySet
    , empty
    , singleton
    , insert
    , member
    , len
    , fromList
    , toList
    ) where
 
data MySet a = Nil
             | Node (MySet a) (MySet a) a
               deriving (Eq)
 
toList :: MySet a -> [a]
toList Nil = []
toList (Node l r a) = a : toList l ++ toList r
 
fromList :: Ord a => [a] -> MySet a
fromList = foldl (flip insert) Nil
 
instance Show a => Show (MySet a) where
    show = ("fromList " ++) . show . toList
 
empty :: MySet a
empty = Nil
 
singleton :: a -> MySet a
singleton = Node Nil Nil
 
insert :: Ord a => a -> MySet a -> MySet a
insert a Nil       = singleton a
insert a n@(Node l r a')
       | a < a'    = Node (insert a l) r a'
       | a > a'    = Node l (insert a r) a'
       | otherwise = n
 
member :: Ord a => a -> MySet a -> Bool
member _ Nil       = False
member a (Node l r a')
       | a < a'    = member a l
       | a > a'    = member a r
       | otherwise = True
 
len :: MySet a -> Int
len Nil          = 0
len (Node l r _) = 1 + len l + len r


Содержимое myset.cabal.
Кликните здесь для просмотра всего текста
Код
name:                myset
version:             0.1.0.0
-- synopsis:
-- description:
license:             MIT
license-file:        LICENSE
author:              nameless
maintainer:          nameless@no.such.domain.org
-- copyright:
category:            Data
build-type:          Simple
cabal-version:       >=1.8

library
  exposed-modules:     Data.MySet
  -- other-modules:
  build-depends:       base ==4.5.*
  hs-source-dirs:      src
  ghc-options:         -Wall -Werror


Теперь мы хотим добавить тесты, для этого в .cabal-файл нужно добавить секцию test-suite:
Код
test-suite tests
  main-is:             TestSuite.hs
  hs-source-dirs:      src test

  type:                exitcode-stdio-1.0
  build-depends:       base ==4.5.*, test-framework ==0.8.*, test-framework-hunit ==0.3.*,
                       HUnit ==1.2.*
Как можно заметить, зависимости сборки test-suite отличаются от зависимостей сборки самой библиотеки; если при сборке не будет указан ключ --enable-tests, то тесты выполняться не будут, и зависимости для тестов тоже не будут установлены.

Теперь по организации тестов: я для каждого модуля This.Is.Module.Name (который располагается в директории src), который собираюсь тестировать, создаю модуль с названием This.Is.Module.Name.Tests в директории test с определениями тестов.

test/Data/MySet/Tests.hs.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module Data.MySet.Tests (tests) where
 
import Test.Framework (Test)
import Test.Framework.Providers.HUnit
import Test.HUnit hiding (Test)
 
import Data.MySet
 
import Control.Applicative
 
testAddDuplicate :: Test
testAddDuplicate =
    testCase "add duplicate to set" $ do
      assertBool "set mustn't contain duplicates" $ len set1 == len set2
          where set1 = fromList [1,2,3]
                set2 = insert 2 set1
 
tests :: [Test]
tests = [testAddDuplicate]


И, наконец, код test/TestSuite.hs.
Кликните здесь для просмотра всего текста
Haskell
1
2
3
4
5
6
7
8
9
module Main where
 
import Test.Framework (defaultMain, testGroup)
import qualified Data.MySet.Tests
 
main :: IO ()
main = defaultMain tests
    where
      tests = [ testGroup "Data.MySet.Tests" Data.MySet.Tests.tests ]


Структура директорий проекта:
Название: Снимок экрана от 2014-04-10 21:15:24.png
Просмотров: 38

Размер: 4.5 Кб
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 15:37  [ТС] 5
Цитата Сообщение от Nameless One Посмотреть сообщение
Рассмотрим простой пример: библиотека, предоставляющая тип «множество».
Теперь добавим в эту библиотеку еще один тип и сделаем import Data.MySet, назовем его Data.MyFunc.
Библиотека соберется. Но если ты захочешь покопаться отдельно в Data.MyFunc (запустить его отдельно через runhaskell), то он не сможет найти Data.MySet.
Вот и получается, что либо постоянно выскакивай из редактора и запускай тесты после каждого чиха, либо пиши все в одном файле. Вместе с тестами.
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 15:40 6
Цитата Сообщение от aaleksander Посмотреть сообщение
Но если ты захочешь покопаться отдельно в Data.MyFunc, то он не сможет найти Data.MySet.
Кто «он»?

Цитата Сообщение от aaleksander Посмотреть сообщение
Вот и получается, что либо постоянно выскакивай из редактора
Зачем?
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 15:50  [ТС] 7
Вот такой код соберется в пакет:
Haskell
1
2
3
4
module Data.MyFunc where
import Data.MySet
 
.......
Но если зайти в директорию Data и запустить ghci MyFunc.hs, он напишет "Could not find module Data.MySet"
У меня, по крайней мере так.
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 15:56 8
Цитата Сообщение от aaleksander Посмотреть сообщение
Но если зайти в директорию Data и запустить ghci MyFunc.hs
Напрямую ghci не использую, а использую Emacs, и у меня всё прекрасно работает.
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 16:00 9
Цитата Сообщение от Nameless One Посмотреть сообщение
и у меня всё прекрасно работает.
Как правильно отделить пакет библиотеки от тестов?


На скриншоте видно, как в интерпретаторе загружен модуль Data.MySet.Tests и выводится информация о типе tests не смотря на то, что Data.MySet.Tests импортирует модуль Data.MySet, который вообще находится в другой директории.
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 16:02  [ТС] 10
Цитата Сообщение от Nameless One Посмотреть сообщение
Напрямую ghci не использую, а использую Emacs, и у меня всё прекрасно работает.
Ну я для примера. Можно заменить на runhaskell.
У меня Sublime Text. В нем на кнопку F9 записан runhaskell с редактируемым файлом в качестве параметра. Не работает.
Можно посмотреть строку запуска для Emacsa?
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 16:06 11
Цитата Сообщение от aaleksander Посмотреть сообщение
Можно посмотреть строку запуска для Emacsa?
Строки запуска нет. Я нажимаю комбинацию Ctrl-L, при этом вызывается функция haskell-process-load-file.

Вот на всякий случай моя конфигурация haskell-mode:
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
;;; haskell setup
(require 'ghci-completion)
;;; Haskell mode customization
(defun nameless/haskell-mode-hook ()
  "Custom haskell-mode hook."
 (local-set-key [return] 'newline-and-indent))
 
(add-hook 'haskell-mode-hook 'nameless/haskell-mode-hook)
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
(setq haskell-font-lock-symbols t)
 
(add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion)
 
(add-to-list 'auto-mode-alist
             '("\\.hs$" . haskell-mode))
 
(eval-after-load "haskell-mode"
  '(define-key haskell-mode-map (kbd "C-c C-c") 'haskell-compile))
 
(eval-after-load "haskell-cabal"
  '(define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-compile))
 
(eval-after-load "haskell-mode"
  '(progn
     (define-key haskell-mode-map (kbd "C-x C-d") nil)
     (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
     (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file)
     (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch)
     (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
     (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
     (define-key haskell-mode-map (kbd "C-c M-.") nil)
     (define-key haskell-mode-map (kbd "C-c C-d") nil)))
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 16:07  [ТС] 12
Цитата Сообщение от Nameless One Посмотреть сообщение
На скриншоте видно, как в интерпретаторе загружен модуль Data.MySet.Tests и выводится информация о tests не смотря на то, что Data.MySet.Tests импортирует модуль Data.MySet, который вообще находится в другой директории.
Data.MySet уже заинстален? Тогда да. А если нет?
Короче, буду по старинке.
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 16:13 13
Цитата Сообщение от aaleksander Посмотреть сообщение
Data.MySet уже заинстален? Тогда да. А если нет?
А без разницы. Вот тебе скриншот с двумя файлами Foo.hs и Main.hs, созданными во временной директории (т. е. это вообще не Cabal-проект и установить я их никак не мог)

Как правильно отделить пакет библиотеки от тестов?


Слева сверху — Foo.hs

Слева снизу — Main.hs

Загружаю в интерпретатор (справа) Main.hs, запускаю функцию main. Всё работает.
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 16:14  [ТС] 14
Сейчас заинталлил библиотеку, все получилось.
Внес изменения, чтобы тесты поломались. Пришлось опять делать build и install, чтобы тесты "оживились".
Возможно надо копать в сторону настроек редактора.
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 414
Записей в блоге: 1
10.04.2014, 16:19  [ТС] 15
Цитата Сообщение от Nameless One Посмотреть сообщение
А без разницы. Вот тебе скриншот с двумя файлами Foo.hs и Main.hs
Эдак мы долго будем спорить
Оба файла лежат в одной папке. И не видят друг друга.
Миниатюры
Как правильно отделить пакет библиотеки от тестов?  
0
Эксперт С++
5827 / 3478 / 358
Регистрация: 08.02.2010
Сообщений: 7,448
10.04.2014, 16:25 16
aaleksander, ну тебя же никто не заставляет использовать Sublime Text.

Понятное дело, что поддержка Haskell в Emacs далеко превосходит простой вызов runhaskell, но это по сути единственный на наше время редактор/IDE с поддержкой Haskell, так что особого выбора нет.

Правда, есть ещё Leksah, но оно, во-первых, жутко глючное, во-вторых, мёртвое.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.04.2014, 16:25
Помогаю со студенческими работами здесь

Правильно отделить методы
Как правильно отделить методы, чтобы программа постепенно выполняла 2 действий? Пример: в 1 блоке...

Как определить, какой из подсетей принадлежит пакет IP-пакет?
То есть у Олиферов это всё подробно расписано. Если маршрутизация сделана на основе масок, то надо...

Как правильно подключать файлы и библиотеки.
Может я плохо ищу, а может действительно очень много информации как, но нет как правильно. Я...

Как правильно устанавливать библиотеки из tar.gz
Понадобилось установить библиотеку urlib3, но не нашел pypi, только архив tar.gz А как его...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru