python 驱动开发环境实践

我平常使用Gvim来写代码,所以先配置Vim的python开发环境。

一、配置Vim环境

模版文件准备

为了在vim中能够自动建立测试文件框架,需要建立模版文件,假设我在 ~/.vim/skeleton 目录下建立需要的模版文件,目录结构如下:

/home/bl/.vim/skeleton
|---test.py
|---skeleton_top.py
|---alltests.py
|---skeleton_bottom.py
  1. alltest.py 模版文件

    import unittest
    import sys
    import os
    
    CUR_DIR = os.path.abspath(os.path.dirname(__file__))
    PAR_DIR = os.path.abspath(os.path.join(CUR_DIR, os.path.pardir))
    
    sys.path.append(os.path.abspath(PAR_DIR))
    sys.path.append(os.path.abspath(CUR_DIR))
    
    sys.path.append(os.path.join(CUR_DIR, 'tests'))
    
    tests = os.listdir(os.curdir)
    tests = [n[:-3] for n in tests if n.startswith('test') and n.endswith('.py')]
    
    teststests = os.path.join(os.curdir, 'tests')
    if os.path.isdir(teststests):
        teststests = os.listdir(teststests)
        teststests = [n[:-3] for n in teststests if
                      n.startswith('test') and n.endswith('.py')]
        modules_to_test = tests + teststests
    else:
        modules_to_test = tests
    
    
    def suite():
        alltests = unittest.TestSuite()
        for module in map(__import__, modules_to_test):
            alltests.addTest(unittest.findTestCases(module))
        return alltests
    
    if __name__ == '__main__':
        unittest.main(defaultTest='suite')
    
  2. test.py 模版文件

    import sys
    import os
    
    CUR_DIR = os.path.abspath(os.path.dirname(__file__))
    PAR_DIR = os.path.abspath(os.path.join(CUR_DIR, os.path.pardir))
    
    sys.path.append(os.path.abspath(PAR_DIR))
    sys.path.append(os.path.abspath(CUR_DIR))
    
    from unittest import TestCase
    
    
    class simpleTest(TestCase):
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
    
        def testExample(self):
            self.assertEqual(1, 1)
    
        def testOther(self):
            self.assertNotEqual(0, 1)
    
    if '__main__' == __name__:
        import unittest
        unittest.main()
    
  3. skeleton_top.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    
    #  FileName  :
    # Last Change:
    #   AUTHOR   :  User , [email protected]
    
    """docstring
    """
    
    __revision__ = '0.1'
    
  4. skeleton_bottom.py

    # vim:ts=4:sw=4:ft=python:expandtab:set fdm=indent:
    

vimrc测试相关设置

  1. 设置自动使用模版生成文件

    " 自动使用新文件模板
      autocmd BufNewFile *.py 0r ~/.vim/skeleton/skeleton_bottom.py  
      autocmd BufNewFile test*.py 0r ~/.vim/skeleton/test.py
      autocmd BufNewFile alltests.py 0r ~/.vim/skeleton/alltests.py
      autocmd BufNewFile *.py 0r ~/.vim/skeleton/skeleton_top.py  
    
  2. 设置在vim中执行单元测试

    " Python Unittest 的一些设置
    " 可以让我们在编写 Python 代码及 unittest 测试时不需要离开 vim
    " 键入 :make 或者点击 gvim 工具条上的 make 按钮就自动执行测试用例
      autocmd FileType python compiler pyunit
      autocmd FileType python setlocal makeprg=python\ ./alltests.py
      autocmd BufNewFile,BufRead test*.py setlocal makeprg=python\ %
    
    " 设置make的快捷键,m
      map <C-F8> :make<cr>
    
    " 设置run的快捷键,r
      map <leader>r :w<cr>:!python %<cr>
    

vim其他python设置

  1. 自动删除行尾空格

    " 保存时自动删除行尾空格
        function! RemoveTrailingWhitespace()
            if &ft != "diff"
                let b:curcol = col(".")
                let b:curline = line(".")
                silent! %s/\s\+$//
                silent! %s/\(\s*\n\)\+\%$//
                call cursor(b:curline, b:curcol)
            endif
        endfunction
        autocmd BufWritePre *.py call RemoveTrailingWhitespace() 
    
  2. 自动保存文件名

    " 自动保存文件名
    function! Filename_Save() "
        let pattern =  '^#\s*FileName\s*:'
        let row = search(pattern, 'n')
        if row  != 0 && row <10
            let curstr = getline(row)
            let col = match( curstr , 'FileName\s*:')
            let spacestr = repeat(' ',col-1)
            let buffilename = bufname("%")
            let buffilename = strpart(buffilename,strridx(buffilename,"/")+1)
            "echo strpart(bufname("%"),strridx(bufname("%"),"/"))
            let newline = '#' . spacestr . 'FileName  :  ' . buffilename
            call setline(row, newline)
        endif
    endfunction "
    au BufWritePre *.py           call Filename_Save()
    
  3. 自动修改最后修改日期

    "Last change用到的函数,返回时间,能够自动调整位置
    function! TimeStamp(...)"
        let sbegin = ''
        let send = ''
        if a:0 >= 1
            let sbegin = a:1.'\s*'
            if a:1 == '*'
                let sbegin = '\' . sbegin
            endif
        endif
        if a:0 >= 2
            let send = ' '.a:2
        endif
        let pattern =  'Last Change:.*'
            \. send
        let pattern = '^\s*' . sbegin . pattern . '\s*$'
        "let now = strftime('%Y年%m月%d日 %H时%M分%S秒',
        let now = strftime('%Y年%m月%d日',localtime())
        let row = search(pattern, 'n')
        if row  != 0
            let curstr = getline(row)
            let col = match( curstr , 'Last')
            let leftcol = match(curstr,sbegin)
            let spacestr = repeat(' ',col - len(a:1)-leftcol)
            let leftspacestr = repeat(' ',leftcol)
            let now = leftspacestr . a:1 . spacestr . 'Last Change:  '
                \. now . send
            call setline(row, now)
        endif
    endfunction"
    
    # 保存时自动 修改更改时间
    au BufWritePre *.py           call TimeStamp('#')
    
  4. vim-flake8 插件

能够自动检查python代码是否符合 pep8 风格,默认快捷键是 F7

  1. pytest 插件(主页)

我自己并不使用 pytest , 但是简单看了一下,挺方便的,需要安装。

pip install -U pytest

vim 有一个 pytest的插件可以配合使用,感兴趣可以试一下。

二、测试框架建立

完成上面的准备之后,开始搭建一个演示用的测试框架项目 TDDtest 。

目录及范例测试文件

$ mkdir -p TDDtest/tests/
  • 现在目录结构是

    /home/bl/TDDtest
          |---
          |---tests
    
  • 建立测试整个项目的文件 alltests.py

    $ cd TDDtest
    $ vim alltests.py
    
    vim会使用模版自动生成一个 alltests.py 文件,保存关闭。
    
    $ python alltests.py 
    
    返回 
    
        --------------------
    
        Ran 0 tests in 0.000s
    
        OK
    证明 alltests.py 运行正常,但没有找到单元测试用例。
    
  • 在 tests 目录下建立单元测试文件

    $ cd tests
    $ vim test1.py
    
    只要是test开头的.py文件,vim都会用单元测试模版填充新文件。保存后运行
    
    $ python test1.py -v
    
        testExample (__main__.simpleTest) ... ok
        testOther (__main__.simpleTest) ... ok
        --------------------
        Ran 2 tests in 0.000s
        OK
    
  • 测试导入模块进行测试

    $ cd ..
    $ vim a.py
    
    添加一个实验性的函数
    
        def func_a():
            pass
    
    在 tests/test1.py 中增加
    
        import a
    
        class simpleTest(TestCase):
            def setUp(self):
                ...
    
            def testImportFunc(self):
                res = a.func_a()
                self.assertIsNone(res)
    
    $ python alltests.py -v 
    
        testExample (test1.simpleTest) ... ok
        testOther (test1.simpleTest) ... ok
        testImportFunc (test1.simpleTest) ... ok
    
        ----------------------------------------------------------------------
        Ran 3 tests in 0.002s
    
        OK
    

三、基本使用

  • 测试整个项目

    $ python alltests.py
    
  • 测试单个文件

    $ python tests/test1.py
    
  • 增加测试文件

    使用 vim 在tests目录中建立以 test 开头的.py文件。
    
  • vim中快捷测试test

    ,r         执行当前编辑的测试文件
    ctrl+F8    执行 alltests.py
    

完整的样例文件

1.目录结构

    /home/bl/TDDtest
    |---
    |---alltests.py
    |---a.py
    |---tests
    |    |---test1.py

2. alltests.py (略,未改变模版)

3. a.py

    #!/usr/bin/env python
    # -*- coding: UTF-8 -*-

    #  FileName  :  a.py
    # Last Change:  2014年07月08日
    #   AUTHOR   :  BaiLiang , [email protected]

    """
        试验 unittest
    """

    def func_a():
        pass

    # vim:ts=4:sw=4:ft=python:expandtab:set fdm=indent:

4. test1.py

        #!/usr/bin/env python
        # -*- coding: UTF-8 -*-

        #  FileName  :  test1.py
        # Last Change:  2014年07月08日
        #   AUTHOR   :  BaiLiang , [email protected]

        """
            测试单元测试案例
        """

        __revision__ = '0.1'

        import sys
        import os

        CUR_DIR = os.path.abspath(os.path.dirname(__file__))
        PAR_DIR = os.path.abspath(os.path.join(CUR_DIR, os.path.pardir))

        sys.path.append(os.path.abspath(PAR_DIR))
        sys.path.append(os.path.abspath(CUR_DIR))

        from unittest import TestCase
        import a


        class simpleTest(TestCase):
            def setUp(self):
                pass

            def tearDown(self):
                pass

            def testExample(self):
                self.assertEqual(1, 1)

            def testOther(self):
                self.assertNotEqual(0, 1)

            def testImportFunc(self):
                res = a.func_a()
                self.assertIsNone(res)

        if '__main__' == __name__:
            import unittest
            unittest.main()

        # vim:ts=4:sw=4:ft=python:expandtab:set fdm=indent:

你可能感兴趣的:(python 驱动开发环境实践)