混合简介
在本指南中,我们将学习如何使用自己的监督树,配置,测试等来构建完整的Elixir应用程序。
该应用程序用作分布式键值存储。我们将把键值对组织成桶并将这些桶分布到多个节点上。我们还将构建一个简单的客户端,使我们能够连接到任何节点并发送请求,例如:
CREATE shopping OK PUT shopping milk 1 OK PUT shopping eggs 3 OK GET shopping milk 1 OK DELETE shopping eggs OK
为了构建我们的键值应用程序,我们将使用三种主要工具:
- OTP (开放电信平台)是一套随Erlang一起提供的库。Erlang开发人员使用OTP构建健壮的容错应用程序。在本章中,我们将探讨OTP与Elixir结合的方面,包括监督树,活动经理等;
- Mix是一个随Elixir一起提供的构建工具,提供创建,编译,测试应用程序,管理其依赖关系等等的任务;
- ExUnit是一个与Elixir一起提供的基于测试单元的框架;在本章中,我们将使用Mix创建我们的第一个项目,并探讨OTP,Mix和ExUnit中的不同功能。本指南需要Elixir v1.5.0或更高版本。您可以按照入门指南第一章中所述
elixir --version
的步骤,根据需要检查Elixir版本并安装更新版本。如果您对本指南有任何疑问或改进,请通过 Elixir论坛或问题跟踪器等讨论渠道进行讨论。您的意见非常重要,可以帮助我们保证指南的可访问性和最新性!本指南的最终代码位于此存储库中并可以作为参考。Elixir指南也以EPUB格式提供:
我们的第一个项目
当您安装Elixir,除了获得elixir
,elixirc
和iex
可执行文件,您还可以获得一个名为可执行脚本Elixirmix
。
让我们通过mix new
从命令行调用来创建我们的第一个项目。我们将传递项目名称作为参数(kv
在这种情况下),并告诉Mix,我们的主模块应该是全大写的KV
,而不是默认的,这应该是Kv
:
$ mix new kv --module KV
Mix将创建一个以kv
其中的几个文件命名的目录:
* creating README.md * creating .gitignore * creating mix.exs * creating config * creating config/config.exs * creating lib * creating lib/kv.ex * creating test * creating test/test_helper.exs * creating test/kv_test.exs
让我们简要地看看这些生成的文件。
注意:Mix是一个Elixir可执行文件。这意味着为了运行
mix
,您需要在PATH中同时包含可执行文件mix
和elixir
可执行文件。这就是安装Elixir时会发生的情况。
项目编译
mix.exs
我们的新项目文件夹(kv
)中生成了一个名为文件的文件,其主要职责是配置我们的项目。我们来看看它:
defmodule KV.Mixfile do use Mix.Project def project do [ app: :kv, version: "0.1.0", elixir: "~> 1.6-dev", start_permanent: Mix.env == :prod, deps: deps() ] end # Run "mix help compile.app" to learn about applications. def application do [ extra_applications: [:logger] ] end # Run "mix help deps" to learn about dependencies. defp deps do [ # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, ] end end
我们mix.exs
定义了两个公共函数:project
返回项目名称和版本等项目配置,以及application
用于生成应用程序文件的项目配置。
还有一个名为的私有函数deps
,它从project
函数中调用,它定义了我们的项目依赖关系。deps
不需要定义为单独的功能,但它有助于保持项目配置的整洁。
Mix还会在lib/kv.ex
一个包含一个函数的模块中生成一个文件,该文件名为hello
:
defmodule KV do @moduledoc """ Documentation for KV. """ @doc """ Hello world. ## Examples iex> KV.hello :world """ def hello do :world end end
这个结构足以编译我们的项目:
$ cd kv $ mix compile
将产出:
Compiling 1 file (.ex) Generated kv app
lib/kv.ex
文件已编译,kv.app
生成了一个名为的应用程序清单,并按照“入门指南”中的说明合并了所有协议。所有编译工件都_build
使用mix.exs
文件中定义的选项放置在目录中。
项目编译完成后,您可以iex
运行以下命令在项目中启动会话:
$ iex -S mix
运行测试
Mix还为运行我们的项目测试生成了适当的结构。混合项目通常遵循目录中每个文件在目录中具有<filename>_test.exs
文件的约定。出于这个原因,我们已经可以找到对应于我们的文件。在这一点上它并没有太多的作用:testlibtest/kv_test.exslib/kv.ex
defmodule KVTest do use ExUnit.Case doctest KV test "greets the world" do assert KV.hello() == :world end end
重要的是要注意几件事情:
- 测试文件是一个Elixir脚本文件(
.exs
)。这很方便,因为我们不需要在运行它们之前编译测试文件;
- 我们定义一个名为test module
KVTest
,用于ExUnit.Case
注入测试API并使用test/2
宏定义一个简单的测试;
Mix还生成了一个名为test/test_helper.exs
它的文件,负责设置测试框架:
ExUnit.start()
在我们运行测试之前,每次都需要这个文件。我们可以运行测试mix test
:
Compiled lib/kv.ex Generated kv app .. Finished in 0.04 seconds 2 tests, 0 failures Randomized with seed 540224
请注意,通过运行mix test
,Mix已经编译了源文件并再次生成了应用程序清单。这是因为Mix支持多种环境,我们将在下一节中探讨。
此外,您可以看到ExUnit为每个成功的测试打印一个点,并自动随机测试。让我们让测试失败并看看会发生什么。
将断言更改test/kv_test.exs
为以下内容:
assert KV.hello() == :oops
现在再次运行mix test
(注意这次不会有编译):
1) test greets the world (KVTest) test/kv_test.exs:5 Assertion with == failed code: assert KV.hello() == :oops left: :world right: :oops stacktrace: test/kv_test.exs:6: (test) . Finished in 0.05 seconds 2 tests, 1 failure
对于每次故障,ExUnit都会打印一份详细报告,其中包含测试用例的测试名称,失败的代码以及==
操作员左侧和右侧(rhs)的值。
在失败的第二行中,正好位于测试名称下方,有测试定义的位置。如果您完整地复制测试位置(包括文件和行号)并将其附加到mix test
,则Mix将加载并运行该特定测试:
$ mix test test/kv_test.exs:5
这个快捷方式在构建我们的项目时非常有用,它允许我们通过运行单个测试来快速迭代。
最后,堆栈跟踪与失败本身相关,提供有关测试的信息以及经常从源文件中生成失败的位置。
环境
Mix支持“环境”的概念。它们允许开发人员为特定场景自定义编译和其他选项。默认情况下,Mix理解三种环境:
:dev
- Mix任务(比如compile
)默认运行的那个
:test
-被mix test
:prod
- 您将用于在生产中运行项目的人员
该环境仅适用于当前项目。正如我们稍后会看到的那样,添加到项目中的任何依赖项都将默认在:prod
环境中运行。
每环境定制可以通过访问来完成的Mix.env
功能,在你的mix.exs
文件,它返回当前环境作为一个原子。这就是我们在:start_permanent
选项中使用的:
def project do [..., start_permanent: Mix.env == :prod, ...] end
如果为true,则该:start_permanent
选项将以永久模式启动应用程序,这意味着如果应用程序的监督树关闭,Erlang VM将崩溃。请注意,我们不希望在开发和测试中发生此行为,因为为了进行故障排除,保持VM实例在这些环境中运行非常有用。
:dev
除了默认为环境的test
任务外,混合将默认为:test
环境。环境可以通过MIX_ENV
环境变量进行更改:
$ MIX_ENV=prod mix compile
或在Windows上:
> set "MIX_ENV=prod" && mix compile
Mix是一个构建工具,因此,它并不总是在生产中可用,特别是如果您的团队使用明确的构建步骤。因此,建议
Mix.env
仅在配置文件和内部进行访问mix.exs
,而不要在应用程序代码(lib
)中进行访问。
探索
Mix还有很多,我们将在建设项目时继续探索它。一个总体概述可在混合文档上。
请记住,您始终可以调用帮助任务来列出所有可用的任务:
$ mix help
您可以通过调用获得有关特定任务的更多信息mix help TASK
。
我们来写一些代码吧!