Add some basic tests

This commit is contained in:
Chris de Graaf 2019-08-31 17:33:33 +07:00
parent 810ac5ab28
commit 5adde3ad7c
No known key found for this signature in database
GPG Key ID: 150FFDD9B0073C7B
19 changed files with 202 additions and 53 deletions

8
.gitignore vendored
View File

@ -1,6 +1,6 @@
.DS_Store
*.jl.cov
*.jl.*.cov
*.jl.mem
/docs/build/
/docs/site/
.DS_Store
*.jl.*.cov
*.jl.cov
*.jl.mem

View File

@ -11,6 +11,9 @@ julia:
- 1.2
- 1.3
- nightly
before_script:
- git config --global user.name Tester
- git config --global user.email te@st.er
matrix:
fast_finish: true
allow_failures:

View File

@ -106,12 +106,6 @@ version = "0.2.11"
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[URIParser]]
deps = ["Test", "Unicode"]
git-tree-sha1 = "6ddf8244220dfda2f17539fa8c9de20d6c575b69"
uuid = "30578b45-9adc-5946-b283-645ec420af67"
version = "0.4.0"
[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

View File

@ -1,7 +1,7 @@
name = "PkgTemplates"
uuid = "14b8a8f1-9102-5b29-a752-f990bacb7fe1"
authors = ["Chris de Graaf <chrisadegraaf@gmail.com>"]
version = "0.6.2"
version = "0.7.0"
[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
@ -11,14 +11,14 @@ Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
URIParser = "30578b45-9adc-5946-b283-645ec420af67"
[compat]
julia = "1"
[extras]
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
ReferenceTests = "324d217c-45ce-50fc-942e-d289b448e8cf"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Suppressor", "Test"]
test = ["Random", "ReferenceTests", "Test"]

View File

@ -11,7 +11,6 @@ using REPL.TerminalMenus: MultiSelectMenu, RadioMenu, request
using Mustache: entityMap, render
using Parameters: @with_kw
using URIParser: URI
export
Template,
@ -36,5 +35,6 @@ abstract type Plugin end
include("template.jl")
include("generate.jl")
include("plugin.jl")
# include("interactive.jl")
end

View File

@ -6,7 +6,6 @@ Generate a package named `pkg` from a [`Template`](@ref).
function (t::Template)(pkg::AbstractString)
endswith(pkg, ".jl") && (pkg = pkg[1:end-3])
pkg_dir = joinpath(t.dir, pkg)
ispath(pkg_dir) && throw(ArgumentError("$pkg_dir already exists"))
try
# Create the directory with some boilerplate inside.

View File

@ -1,14 +1,13 @@
# TODO: Update the allowed failures as new versions come out.
const VersionsOrStrings = Vector{Union{VersionNumber, String}}
const ALLOWED_FAILURES = ["1.3", "nightly"]
const DEFAULT_CI_VERSIONS = VersionsOrStrings([VERSION, "1.0", "nightly"])
const ALLOWED_FAILURES = ["1.3", "nightly"] # TODO: Update this list with new RCs.
const DEFAULT_CI_VERSIONS = VersionsOrStrings([VERSION, default_version(), "nightly"])
format_version(v::VersionNumber) = "$(v.major).$(v.minor)"
format_version(v::AbstractString) = string(v)
function collect_versions(t::Template, versions::Vector)
vs = [format_version(t.julia_version); map(format_version, versions)]
return unique!(sort!(vs))
vs = map(format_version, [t.julia_version, versions...])
return unique(sort(vs))
end
@with_kw struct TravisCI <: BasicPlugin
@ -43,8 +42,8 @@ function view(p::TravisCI, t::Template, pkg::AbstractString)
x86 = Dict{String, String}[]
if p.x86
foreach(versions) do v
p.linux && push!(x86, Dict("JULIA" => v, "OS" => "linux", "ARCH" => "x86"))
p.windows && push!(x86, Dict("JULIA" => v, "OS" => "windows", "ARCH" => "x86"))
p.linux && push!(x86, Dict("JULIA" => v, "OS" => "linux"))
p.windows && push!(x86, Dict("JULIA" => v, "OS" => "windows"))
end
end
@ -128,10 +127,10 @@ function view(p::CirrusCI, t::Template, ::AbstractString)
end
@with_kw struct GitLabCI <: BasicPlugin
file::String
file::String = default_file("gitlab-ci.yml")
documentation::Bool = true
coverage::Bool = true
extra_versions::Vector{VersionNumber} = [v"1.0"]
extra_versions::VersionsOrStrings = ["1.0"] # Nightly has no Docker image.
end
gitignore(p::GitLabCI) = p.coverage ? COVERAGE_GITIGNORE : String[]

View File

@ -93,7 +93,7 @@ function render_plugin(p::Gitignore, t::Template)
end
function gen_plugin(p::Gitignore, t::Template, pkg_dir::AbstractString)
gen_file(joinpath(pkg_dir, ".gitignore"), render_plugin(p, t))
t.git && gen_file(joinpath(pkg_dir, ".gitignore"), render_plugin(p, t))
end
@with_kw struct Tests <: BasicPlugin
@ -121,7 +121,7 @@ function gen_plugin(p::Tests, t::Template, pkg_dir::AbstractString)
proj = current_project()
try
Pkg.activate(pkg_dir)
Pkg.update() # Clean up both Manifest.toml and Project.toml.
Pkg.update()
finally
proj === nothing ? Pkg.activate() : Pkg.activate(proj)
end

View File

@ -1,13 +1,12 @@
const DEFAULT_USER = LibGit2.getconfig("github.user", "")
const DEFAULT_VERSION = VersionNumber(VERSION.major)
const DEFAULT_AUTHORS = let
default_plugins() = [Gitignore(), License(), Readme(), Tests()]
default_user() = LibGit2.getconfig("github.user", "")
default_version() = VersionNumber(VERSION.major)
function default_authors()
name = LibGit2.getconfig("user.name", "")
isempty(name) && return ""
email = LibGit2.getconfig("user.email", "")
if isempty(name)
""
else
isempty(email) ? name : "$name <$email>"
end
return isempty(email) ? name : "$name <$email>"
end
"""
@ -18,17 +17,17 @@ Records common information used to generate a package.
## Keyword Arguments
### User Options
- `user::AbstractString="$DEFAULT_USER"`: GitHub (or other code hosting service) username.
- `user::AbstractString="$(default_user())"`: GitHub (or other code hosting service) username.
The default value comes from the global Git config (`github.user`).
If no value is obtained, an `ArgumentError` is thrown.
- `authors::Union{AbstractString, Vector{<:AbstractString}}="$DEFAULT_AUTHORS"`: Package authors.
- `authors::Union{AbstractString, Vector{<:AbstractString}}="$(default_authors())"`: Package authors.
Supply a string for one author or an array for multiple.
Like `user`, it takes its default value from the global Git config (`user.name` and `user.email`).
### Package Options
- `host::AbstractString="github.com"`: URL to the code hosting service where packages will reside.
- `dir::AbstractString="$(contractuser(Pkg.devdir()))"`: Directory to place packages in.
- `julia_version::VersionNumber=$(repr(DEFAULT_VERSION))`: Minimum allowed Julia version.
- `julia_version::VersionNumber=$(repr(default_version()))`: Minimum allowed Julia version.
- `develop::Bool=true`: Whether or not to `develop` new packages in the active environment.
### Git Options
@ -39,13 +38,12 @@ Records common information used to generate a package.
### Template Plugins
- `plugins::Vector{<:Plugin}=Plugin[]`: A list of [`Plugin`](@ref)s used by the template.
- `disabled_defaults::Vector{DataType}=DataType[]`: Default plugins to disable.
- `disable_defaults::Vector{DataType}=DataType[]`: Default plugins to disable.
The default plugins are [`Readme`](@ref), [`License`](@ref), [`Tests`](@ref), and [`Gitignore`](@ref).
To override a default plugin instead of disabling it altogether, supply it via `plugins`.
### Interactive Usage
- `interactive::Bool=false`: When set, the template is created interactively, filling unset keywords with user input.
- `fast::Bool=false`: Skips prompts for any unsupplied keywords except `user` and `plugins`, accepting default values.
"""
struct Template
authors::Vector{String}
@ -67,21 +65,19 @@ function Template(::Val{false}; kwargs...)
user = getkw(kwargs, :user)
isempty(user) && throw(ArgumentError("No user set, please pass user=username"))
host = getkw(kwargs, :host)
host = URI(occursin("://", host) ? host : "https://$host").host
authors = getkw(kwargs, :authors)
authors isa Vector || (authors = map(strip, split(authors, ",")))
host = replace(getkw(kwargs, :host), r".*://" => "")
dir = abspath(expanduser(getkw(kwargs, :dir)))
disabled = getkw(kwargs, :disabled_defaults)
defaults = [Readme, License, Tests, Gitignore]
plugins = map(T -> T(), filter(T -> !(T in disabled), defaults))
append!(plugins, getkw(kwargs, :plugins))
disabled = getkw(kwargs, :disable_defaults)
enabled = filter(p -> !(typeof(p) in disabled), default_plugins())
append!(enabled, getkw(kwargs, :plugins))
# This comprehension resolves duplicate plugin types by overwriting,
# which means that default plugins get replaced by user values.
plugin_dict = Dict(typeof(p) => p for p in plugins)
plugins = Dict(typeof(p) => p for p in enabled)
return Template(
authors,
@ -91,7 +87,7 @@ function Template(::Val{false}; kwargs...)
host,
getkw(kwargs, :julia_version),
getkw(kwargs, :manifest),
plugin_dict,
plugins,
getkw(kwargs, :ssh),
user,
)
@ -106,14 +102,14 @@ getkw(kwargs, k) = get(() -> defaultkw(k), kwargs, k)
# Default Template keyword values.
defaultkw(s::Symbol) = defaultkw(Val(s))
defaultkw(::Val{:authors}) = DEFAULT_AUTHORS
defaultkw(::Val{:authors}) = default_authors()
defaultkw(::Val{:develop}) = true
defaultkw(::Val{:dir}) = Pkg.devdir()
defaultkw(::Val{:disabled_defaults}) = DataType[]
defaultkw(::Val{:disable_defaults}) = DataType[]
defaultkw(::Val{:git}) = true
defaultkw(::Val{:host}) = "github.com"
defaultkw(::Val{:julia_version}) = DEFAULT_VERSION
defaultkw(::Val{:julia_version}) = default_version()
defaultkw(::Val{:manifest}) = false
defaultkw(::Val{:plugins}) = Plugin[]
defaultkw(::Val{:ssh}) = false
defaultkw(::Val{:user}) = DEFAULT_USER
defaultkw(::Val{:user}) = default_user()

3
test/fixtures/Basic/.gitignore.txt vendored Normal file
View File

@ -0,0 +1,3 @@
.DS_Store
/Manifest.toml
/dev/

19
test/fixtures/Basic/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2019 tester
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
test/fixtures/Basic/Manifest.toml.txt vendored Normal file
View File

@ -0,0 +1,2 @@
# This file is machine-generated - editing it directly is not advised

13
test/fixtures/Basic/Project.toml.txt vendored Normal file
View File

@ -0,0 +1,13 @@
name = "Basic"
uuid = "5b7e9947-ddc0-4b3f-9b55-0d8042f74170"
authors = ["tester"]
version = "0.1.0"
[compat]
julia = "1"
[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[targets]
test = ["Test"]

1
test/fixtures/Basic/README.md.txt vendored Normal file
View File

@ -0,0 +1 @@
# Basic

5
test/fixtures/Basic/src/Basic.jl.txt vendored Normal file
View File

@ -0,0 +1,5 @@
module Basic
greet() = print("Hello World!")
end # module

View File

@ -0,0 +1,6 @@
using Basic
using Test
@testset "Basic.jl" begin
# Write your tests here.
end

25
test/generate.jl Normal file
View File

@ -0,0 +1,25 @@
default_files(pkg::AbstractString) = [
".gitignore",
"LICENSE",
"Manifest.toml",
"Project.toml",
"README.md",
"src/$pkg.jl",
"test/runtests.jl",
]
function reference_test(pkg_dir::AbstractString, path::AbstractString)
pkg = basename(pkg_dir)
path = replace(path, "/" => path_separator)
# All fixture files are .txt because otherwise ReferenceTests/FileIO can't handle them.
reference = joinpath(@__DIR__, "fixtures", pkg, path * ".txt")
observed = read(joinpath(pkg_dir, path), String)
@test_reference reference observed
end
@testset "Default package" begin
pkg = "Basic"
t = tpl(; develop=false, authors=USER)
t(pkg)
foreach(f -> reference_test(joinpath(t.dir, pkg), f), default_files(pkg))
end

View File

@ -0,0 +1,32 @@
using Base.Filesystem: path_separator
using Pkg: Pkg
using Random: Random
using Test: @test, @testset, @test_throws
using ReferenceTests: @test_reference
using PkgTemplates
const PT = PkgTemplates
const PKG = "TestPkg"
const USER = "tester"
Random.seed!(1)
tpl(; kwargs...) = Template(; user=USER, kwargs...)
@testset "PkgTemplates.jl" begin
mktempdir() do dir
Pkg.activate(dir)
pushfirst!(DEPOT_PATH, dir)
try
include("template.jl")
include("generate.jl")
# include("plugin.jl")
# include("interactive.jl")
finally
popfirst!(DEPOT_PATH)
end
end
end

52
test/template.jl Normal file
View File

@ -0,0 +1,52 @@
@testset "Template constructor" begin
@testset "user" begin
if isempty(PT.default_user())
@test_throws ArgumentError Template()
haskey(ENV, "CI") && run(`git config --global github.user $USER`)
end
@test Template().user == PT.default_user()
end
@testset "authors" begin
@test tpl(; authors=["a"]).authors == ["a"]
@test tpl(; authors="a").authors == ["a"]
@test tpl(; authors="a,b").authors == ["a", "b"]
@test tpl(; authors="a, b").authors == ["a", "b"]
end
@testset "host" begin
@test tpl(; host="https://foo.com").host == "foo.com"
end
@testset "dir" begin
@test tpl(; dir="/foo/bar").dir == "/foo/bar"
@test tpl(; dir="foo").dir == abspath("foo")
@test tpl(; dir="~/foo").dir == abspath(expanduser("~/foo"))
end
@testset "plugins / disabled_defaults" begin
function test_plugins(plugins, expected, disabled=DataType[])
t = tpl(; plugins=plugins, disable_defaults=disabled)
@test issetequal(values(t.plugins), expected)
end
defaults = PT.default_plugins()
test_plugins([], defaults)
test_plugins([Citation()], union(defaults, [Citation()]))
# Overriding a default plugin.
gi = Gitignore(; dev=false)
test_plugins([gi], union(setdiff(defaults, [Gitignore()]), [gi]))
# Disabling a default plugin.
test_plugins([], setdiff(defaults, [Gitignore()]), [Gitignore])
end
end
@testset "hasplugin" begin
t = tpl(; plugins=[Documenter{TravisCI}()])
@test PT.hasplugin(t, typeof(first(PT.default_plugins())))
@test PT.hasplugin(t, Documenter)
@test PT.hasplugin(t, _ -> true)
@test !PT.hasplugin(t, _ -> false)
@test !PT.hasplugin(t, Citation)
@test !PT.hasplugin(t, PT.is_ci)
end